diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 25a7c78eda..6d9dc3fec5 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -327,6 +327,7 @@ if( KICAD_SPICE ) sim/sim_model_xspice.cpp sim/sim_model_ideal.cpp sim/sim_model_ngspice.cpp + sim/sim_model_passive.cpp sim/sim_model_spice.cpp sim/sim_model_source.cpp sim/sim_model_subckt.cpp diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 48dde7e077..0ce409aa14 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -221,6 +221,9 @@ void DIALOG_SIM_MODEL::updateModelParamsTab() m_firstCategory = m_paramGrid->Append( new wxPropertyCategory( "DC" ) ); m_paramGrid->HideProperty( "DC" ); + m_paramGrid->Append( new wxPropertyCategory( "Capacitance" ) ); + m_paramGrid->HideProperty( "Capacitance" ); + m_paramGrid->Append( new wxPropertyCategory( "Temperature" ) ); m_paramGrid->HideProperty( "Temperature" ); @@ -242,7 +245,7 @@ void DIALOG_SIM_MODEL::updateModelParamsTab() m_paramGrid->Append( new wxPropertyCategory( "Flags" ) ); m_paramGrid->HideProperty( "Flags" ); - for( int i = 0; i < curModel().GetParamCount(); ++i ) + for( unsigned i = 0; i < curModel().GetParamCount(); ++i ) addParamPropertyIfRelevant( i ); m_paramGrid->CollapseAll(); @@ -309,9 +312,9 @@ void DIALOG_SIM_MODEL::updatePinAssignmentsTab() "Not Connected" ); } - for( int i = 0; i < curModel().GetPinCount(); ++i ) + for( unsigned i = 0; i < curModel().GetPinCount(); ++i ) { - int symbolPinNumber = curModel().GetPin( i ).symbolPinNumber; + unsigned symbolPinNumber = curModel().GetPin( i ).symbolPinNumber; if( symbolPinNumber == SIM_MODEL::PIN::NOT_CONNECTED ) continue; @@ -319,7 +322,7 @@ void DIALOG_SIM_MODEL::updatePinAssignmentsTab() wxString modelPinString = getModelPinString( i + 1 ); wxArrayString choices; - m_pinAssignmentsGrid->SetCellValue( symbolPinNumber - 1, + m_pinAssignmentsGrid->SetCellValue( static_cast( symbolPinNumber - 1 ), static_cast( PIN_COLUMN::MODEL ), modelPinString ); } @@ -337,7 +340,7 @@ void DIALOG_SIM_MODEL::updatePinAssignmentsGridEditors() wxString modelPinChoicesString = ""; bool isFirst = true; - for( int i = 0; i < curModel().GetPinCount(); ++i ) + for( unsigned i = 0; i < curModel().GetPinCount(); ++i ) { const SIM_MODEL::PIN& modelPin = curModel().GetPin( i ); int modelPinNumber = static_cast( i + 1 ); @@ -386,7 +389,15 @@ void DIALOG_SIM_MODEL::updatePinAssignmentsGridEditors() template void DIALOG_SIM_MODEL::loadLibrary( const wxString& aFilePath ) { - m_library->ReadFile( Prj().AbsolutePath( aFilePath ) ); + const wxString absolutePath = Prj().AbsolutePath( aFilePath ); + + if( !m_library->ReadFile( Prj().AbsolutePath( aFilePath ) ) ) + { + DisplayErrorMessage( this, wxString::Format( _( "Error loading model library '%s'" ), + Prj().AbsolutePath( aFilePath ), aFilePath ), + m_library->GetErrorMessage() ); + } + m_libraryPathInput->SetValue( aFilePath ); m_libraryModels.clear(); @@ -482,6 +493,12 @@ wxPGProperty* DIALOG_SIM_MODEL::newParamProperty( int aParamIndex ) const switch( param.info.type ) { + case TYPE::BOOL: + // TODO. + prop = new wxBoolProperty( paramDescription, param.info.name ); + prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true ); + break; + case TYPE::INT: prop = new SIM_PROPERTY( paramDescription, param.info.name, m_library, curModelSharedPtr(), aParamIndex, SIM_VALUE::TYPE::INT ); @@ -492,9 +509,12 @@ wxPGProperty* DIALOG_SIM_MODEL::newParamProperty( int aParamIndex ) const aParamIndex, SIM_VALUE::TYPE::FLOAT ); break; - case TYPE::BOOL: - prop = new wxBoolProperty( paramDescription, param.info.name ); - prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true ); + //case TYPE::COMPLEX: + // break; + + case TYPE::STRING: + prop = new SIM_PROPERTY( paramDescription, param.info.name, m_library, curModelSharedPtr(), + aParamIndex, SIM_VALUE::TYPE::STRING ); break; default: diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index bd0d6bc6a9..6e6b037ef2 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -26,6 +26,7 @@ #include "netlist_exporter_spice.h" #include #include +#include #include #include #include @@ -175,7 +176,7 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives() else continue; - tao::pegtl::string_input<> in( text.ToStdString()+"\n", "from_content" ); + tao::pegtl::string_input<> in( text.ToStdString() + "\n", "from_content" ); std::unique_ptr root; try @@ -209,12 +210,20 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives() void NETLIST_EXPORTER_SPICE::readLibraryField( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem ) { SCH_FIELD* field = aSymbol.FindField( SIM_LIBRARY::LIBRARY_FIELD ); + wxString path; - if( !field ) + if( field ) + path = field->GetShownText(); + else if( auto model = dynamic_cast( aItem.model.get() ) ) + { + // Special case for legacy models. + int libParamIndex = static_cast( SIM_MODEL_SPICE::SPICE_PARAM::LIB ); + path = model->GetParam( libParamIndex ).value->ToString(); + } + + if( path.IsEmpty() ) return; - wxString path = field->GetShownText(); - if( auto library = SIM_LIBRARY::Create( m_schematic->Prj().AbsolutePath( path ) ) ) m_libraries.try_emplace( path, std::move( library ) ); @@ -239,7 +248,7 @@ void NETLIST_EXPORTER_SPICE::readNameField( SCH_SYMBOL& aSymbol, SPICE_ITEM& aIt if( baseModel ) { aItem.model = SIM_MODEL::Create( *baseModel, - static_cast( m_sortedSymbolPinList.size() ), + m_sortedSymbolPinList.size(), aSymbol.GetFields() ); aItem.modelName = modelName; return; diff --git a/eeschema/sim/ngspice.h b/eeschema/sim/ngspice.h index 3da7290d03..883fdd8f27 100644 --- a/eeschema/sim/ngspice.h +++ b/eeschema/sim/ngspice.h @@ -52,9 +52,9 @@ class NGSPICE : public SPICE_SIMULATOR public: DEFINE_ENUM_CLASS_WITH_ITERATOR( MODEL_TYPE, NONE, - RESISTOR, - CAPACITOR, - INDUCTOR, + //RESISTOR, + //CAPACITOR, + //INDUCTOR, LTRA, TRANLINE, URC, diff --git a/eeschema/sim/ngspice_models.cpp b/eeschema/sim/ngspice_models.cpp index 30c230d10a..78977331be 100644 --- a/eeschema/sim/ngspice_models.cpp +++ b/eeschema/sim/ngspice_models.cpp @@ -99,12 +99,12 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType ) static MODEL_INFO model = {}; return model; } - case MODEL_TYPE::RESISTOR: + /*case MODEL_TYPE::RESISTOR: { static MODEL_INFO model = { "Resistor", "R", "", { "+", "-" }, "Simple linear resistor", // Model parameters { - { "rsh", 103, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Q(), "ohm/m", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "0", "", "Sheet resistance" }, + { "rsh", 103, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Q(), "ohm/m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Sheet resistance" }, { "narrow", 106, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Z(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Narrowing of resistor" }, { "dw", 106, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, ZR(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Narrowing of resistor" }, { "short", 109, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Z(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Shortening of resistor" }, @@ -117,15 +117,15 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType ) { "defw", 104, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, X(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1e-05", "", "Default device width" }, { "w", 104, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, XR(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1e-05", "", "Default device width" }, { "l", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, X(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1e-05", "", "Default device length" }, - { "kf", 110, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Q(), "", SIM_MODEL::PARAM::CATEGORY::NOISE, "0", "", "Flicker noise coefficient" }, - { "af", 111, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Q(), "", SIM_MODEL::PARAM::CATEGORY::NOISE, "0", "", "Flicker noise exponent" }, + { "kf", 110, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Q(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Flicker noise coefficient" }, + { "af", 111, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, Q(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Flicker noise exponent" }, { "tnom", 108, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, XU(), "deg C", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "27", "", "Parameter measurement temperature" }, - { "r", 107, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "ohm", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Resistor model default value" }, + { "r", 107, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "ohm", SIM_MODEL::PARAM::CATEGORY::PRINCIPAL, "0", "", "Resistor model default value" }, { "res", 107, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, R(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "n.a." }, { "bv_max", 112, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "V", SIM_MODEL::PARAM::CATEGORY::LIMITING_VALUES, "1e+99", "", "maximum voltage over resistor" }, - { "lf", 113, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::NOISE, "1", "", "noise area length exponent" }, - { "wf", 114, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::NOISE, "1", "", "noise area width exponent" }, - { "ef", 115, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::NOISE, "1", "", "noise frequency exponent" }, + { "lf", 113, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1", "", "noise area length exponent" }, + { "wf", 114, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1", "", "noise area width exponent" }, + { "ef", 115, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1", "", "noise frequency exponent" }, }, // Instance parameters { @@ -162,10 +162,10 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType ) static MODEL_INFO model = { "Capacitor", "C", "", { "+", "-" }, "Fixed capacitor", // Model parameters { - { "cap", 113, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Model capacitance" }, - { "cj", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "0", "", "Bottom Capacitance per area" }, + { "cap", 113, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::PRINCIPAL, "0", "", "Model capacitance" }, + { "cj", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Bottom Capacitance per area" }, { "cox", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, AR(), "F", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Bottom Capacitance per area" }, - { "cjsw", 102, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "F/m", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "0", "", "Sidewall capacitance per meter" }, + { "cjsw", 102, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "F/m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Sidewall capacitance per meter" }, { "capsw", 102, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, AR(), "F/m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Sidewall capacitance per meter" }, { "defw", 103, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, X(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1e-05", "", "Default width" }, { "w", 103, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, XR(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1e-05", "", "Default width" }, @@ -178,7 +178,7 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType ) { "tc2", 109, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "ohm/deg C^2", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "Second order temp. coefficient" }, { "tnom", 110, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, XU(), "deg C", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "27", "", "Parameter measurement temperature" }, { "di", 111, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "0", "", "Relative dielectric constant" }, - { "thick", 112, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "m", SIM_MODEL::PARAM::CATEGORY::GEOMETRY, "0", "", "Insulator thickness" }, + { "thick", 112, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Insulator thickness" }, { "bv_max", 115, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, {}, "F", SIM_MODEL::PARAM::CATEGORY::LIMITING_VALUES, "1e+99", "", "maximum voltage over capacitance" }, { "c", 104, SIM_MODEL::PARAM::DIR::IN, SIM_VALUE::TYPE::BOOL, {}, "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "", "", "Capacitor model" }, }, @@ -214,14 +214,14 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType ) static MODEL_INFO model = { "Inductor", "L", "", { "+", "-" }, "Fixed inductor", // Model parameters { - { "ind", 100, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "H", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Model inductance" }, + { "ind", 100, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "H", SIM_MODEL::PARAM::CATEGORY::PRINCIPAL, "0", "", "Model inductance" }, { "tc1", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "ohm/deg C", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "First order temp. coefficient" }, { "tc2", 102, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "ohm/deg C^2", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "Second order temp. coefficient" }, { "tnom", 103, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, XU(), "deg C", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "27", "", "Parameter measurement temperature" }, - { "csect", 104, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::GEOMETRY, "0", "", "Inductor cross section" }, - { "length", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "m", SIM_MODEL::PARAM::CATEGORY::GEOMETRY, "0", "", "Inductor length" }, - { "nt", 106, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::GEOMETRY, "0", "", "Model number of turns" }, - { "mu", 107, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "0", "", "Relative magnetic permeability" }, + { "csect", 104, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Inductor cross section" }, + { "length", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Inductor length" }, + { "nt", 106, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Model number of turns" }, + { "mu", 107, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE::TYPE::FLOAT, A(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Relative magnetic permeability" }, { "l", 108, SIM_MODEL::PARAM::DIR::IN, SIM_VALUE::TYPE::BOOL, {}, "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "", "", "Inductor model" }, }, // Instance parameters @@ -248,7 +248,7 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType ) { "sens_cplx", 205, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE::TYPE::COMPLEX, U(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "", "", "ac sensitivity" }, } }; return model; - } + }*/ case MODEL_TYPE::LTRA: { static MODEL_INFO model = { "LTRA", "LTRA", "", { "1+", "1-", "2+", "2-" }, "Lossy transmission line", diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index 7053a7db15..a42de7164a 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -23,14 +23,17 @@ */ #include + #include -#include #include +#include +#include +#include #include +#include #include #include -#include -#include + #include #include #include @@ -45,17 +48,15 @@ namespace SIM_MODEL_PARSER using namespace SIM_MODEL_GRAMMAR; - template struct paramValuePairsSelector : std::false_type {}; + template struct fieldParamValuePairsSelector : std::false_type {}; - template <> struct paramValuePairsSelector : std::true_type {}; - template <> struct paramValuePairsSelector> + template <> struct fieldParamValuePairsSelector : std::true_type {}; + template <> struct fieldParamValuePairsSelector> : std::true_type {}; - template <> struct paramValuePairsSelector> - : std::true_type {}; - template <> struct paramValuePairsSelector> - : std::true_type {}; - template <> struct paramValuePairsSelector> + template <> struct fieldParamValuePairsSelector> : std::true_type {}; + template <> struct fieldParamValuePairsSelector : std::true_type {}; + template <> struct fieldParamValuePairsSelector : std::true_type {}; template struct spiceUnitSelector : std::false_type {}; @@ -140,7 +141,7 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType ) case TYPE::SW_V: return { DEVICE_TYPE::SW, "V", "Voltage-controlled" }; case TYPE::SW_I: return { DEVICE_TYPE::SW, "I", "Current-controlled" }; - case TYPE::D: return { DEVICE_TYPE::D, "", "" }; + case TYPE::D: return { DEVICE_TYPE::D, "", "" }; case TYPE::NPN_GUMMELPOON: return { DEVICE_TYPE::NPN, "GUMMELPOON", "Gummel-Poon" }; case TYPE::PNP_GUMMELPOON: return { DEVICE_TYPE::PNP, "GUMMELPOON", "Gummel-Poon" }; @@ -253,18 +254,18 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType ) switch( aType ) { case TYPE::R: return { "R", "" }; - case TYPE::R_ADV: return { "R", "R" }; + case TYPE::R_ADV: return { "R", "r" }; case TYPE::R_BEHAVIORAL: return { "R", "", "", 0, true }; case TYPE::C: return { "C", "" }; - case TYPE::C_ADV: return { "C", "C", }; + case TYPE::C_ADV: return { "C", "c", }; case TYPE::C_BEHAVIORAL: return { "C", "", "", 0, true }; case TYPE::L: return { "L", "" }; - case TYPE::L_ADV: return { "L", "L" }; + case TYPE::L_ADV: return { "L", "l" }; case TYPE::L_BEHAVIORAL: return { "L", "", "", 0, true }; - case TYPE::TLINE_LOSSY: return { "O", "LTRA" }; + case TYPE::TLINE_LOSSY: return { "O", "ltra" }; case TYPE::TLINE_LOSSLESS: return { "T" }; case TYPE::TLINE_URC: return { "U" }; case TYPE::TLINE_KSPICE: return { "Y" }; @@ -272,69 +273,69 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType ) case TYPE::SW_V: return { "S", "switch" }; case TYPE::SW_I: return { "W", "cswitch" }; - case TYPE::D: return { "D", "D" }; + case TYPE::D: return { "D", "d" }; - case TYPE::NPN_GUMMELPOON: return { "Q", "NPN", "", 1 }; - case TYPE::PNP_GUMMELPOON: return { "Q", "PNP", "", 1 }; + case TYPE::NPN_GUMMELPOON: return { "Q", "npn", "", 1 }; + case TYPE::PNP_GUMMELPOON: return { "Q", "pnp", "", 1 }; - case TYPE::NPN_VBIC: return { "Q", "NPN", "", 4 }; - case TYPE::PNP_VBIC: return { "Q", "PNP", "", 4 }; + case TYPE::NPN_VBIC: return { "Q", "npn", "", 4 }; + case TYPE::PNP_VBIC: return { "Q", "pnp", "", 4 }; - case TYPE::NPN_HICUML2: return { "Q", "NPN", "", 8 }; - case TYPE::PNP_HICUML2: return { "Q", "PNP", "", 8 }; + case TYPE::NPN_HICUML2: return { "Q", "npn", "", 8 }; + case TYPE::PNP_HICUML2: return { "Q", "pnp", "", 8 }; - case TYPE::NJFET_SHICHMANHODGES: return { "M", "NJF", "", 1 }; - case TYPE::PJFET_SHICHMANHODGES: return { "M", "PJF", "", 1 }; - case TYPE::NJFET_PARKERSKELLERN: return { "M", "NJF", "", 2 }; - case TYPE::PJFET_PARKERSKELLERN: return { "M", "PJF", "", 2 }; + case TYPE::NJFET_SHICHMANHODGES: return { "M", "njf", "", 1 }; + case TYPE::PJFET_SHICHMANHODGES: return { "M", "pjf", "", 1 }; + case TYPE::NJFET_PARKERSKELLERN: return { "M", "njf", "", 2 }; + case TYPE::PJFET_PARKERSKELLERN: return { "M", "pjf", "", 2 }; - case TYPE::NMES_STATZ: return { "Z", "NMF", "", 1 }; - case TYPE::PMES_STATZ: return { "Z", "PMF", "", 1 }; - case TYPE::NMES_YTTERDAL: return { "Z", "NMF", "", 2 }; - case TYPE::PMES_YTTERDAL: return { "Z", "PMF", "", 2 }; - case TYPE::NMES_HFET1: return { "Z", "NMF", "", 5 }; - case TYPE::PMES_HFET1: return { "Z", "PMF", "", 5 }; - case TYPE::PMES_HFET2: return { "Z", "NMF", "", 6 }; - case TYPE::NMES_HFET2: return { "Z", "PMF", "", 6 }; + case TYPE::NMES_STATZ: return { "Z", "nmf", "", 1 }; + case TYPE::PMES_STATZ: return { "Z", "pmf", "", 1 }; + case TYPE::NMES_YTTERDAL: return { "Z", "nmf", "", 2 }; + case TYPE::PMES_YTTERDAL: return { "Z", "pmf", "", 2 }; + case TYPE::NMES_HFET1: return { "Z", "nmf", "", 5 }; + case TYPE::PMES_HFET1: return { "Z", "pmf", "", 5 }; + case TYPE::PMES_HFET2: return { "Z", "nmf", "", 6 }; + case TYPE::NMES_HFET2: return { "Z", "pmf", "", 6 }; - case TYPE::NMOS_MOS1: return { "M", "NMOS", "", 1 }; - case TYPE::PMOS_MOS1: return { "M", "PMOS", "", 1 }; - case TYPE::NMOS_MOS2: return { "M", "NMOS", "", 2 }; - case TYPE::PMOS_MOS2: return { "M", "PMOS", "", 2 }; - case TYPE::NMOS_MOS3: return { "M", "NMOS", "", 3 }; - case TYPE::PMOS_MOS3: return { "M", "PMOS", "", 3 }; - case TYPE::NMOS_BSIM1: return { "M", "NMOS", "", 4 }; - case TYPE::PMOS_BSIM1: return { "M", "PMOS", "", 4 }; - case TYPE::NMOS_BSIM2: return { "M", "NMOS", "", 5 }; - case TYPE::PMOS_BSIM2: return { "M", "PMOS", "", 5 }; - case TYPE::NMOS_MOS6: return { "M", "NMOS", "", 6 }; - case TYPE::PMOS_MOS6: return { "M", "PMOS", "", 6 }; - case TYPE::NMOS_BSIM3: return { "M", "NMOS", "", 8 }; - case TYPE::PMOS_BSIM3: return { "M", "PMOS", "", 8 }; - case TYPE::NMOS_MOS9: return { "M", "NMOS", "", 9 }; - case TYPE::PMOS_MOS9: return { "M", "PMOS", "", 9 }; - case TYPE::NMOS_B4SOI: return { "M", "NMOS", "", 10 }; - case TYPE::PMOS_B4SOI: return { "M", "PMOS", "", 10 }; - case TYPE::NMOS_BSIM4: return { "M", "NMOS", "", 14 }; - case TYPE::PMOS_BSIM4: return { "M", "PMOS", "", 14 }; + case TYPE::NMOS_MOS1: return { "M", "nmos", "", 1 }; + case TYPE::PMOS_MOS1: return { "M", "pmos", "", 1 }; + case TYPE::NMOS_MOS2: return { "M", "nmos", "", 2 }; + case TYPE::PMOS_MOS2: return { "M", "pmos", "", 2 }; + case TYPE::NMOS_MOS3: return { "M", "nmos", "", 3 }; + case TYPE::PMOS_MOS3: return { "M", "pmos", "", 3 }; + case TYPE::NMOS_BSIM1: return { "M", "nmos", "", 4 }; + case TYPE::PMOS_BSIM1: return { "M", "pmos", "", 4 }; + case TYPE::NMOS_BSIM2: return { "M", "nmos", "", 5 }; + case TYPE::PMOS_BSIM2: return { "M", "pmos", "", 5 }; + case TYPE::NMOS_MOS6: return { "M", "nmos", "", 6 }; + case TYPE::PMOS_MOS6: return { "M", "pmos", "", 6 }; + case TYPE::NMOS_BSIM3: return { "M", "nmos", "", 8 }; + case TYPE::PMOS_BSIM3: return { "M", "pmos", "", 8 }; + case TYPE::NMOS_MOS9: return { "M", "nmos", "", 9 }; + case TYPE::PMOS_MOS9: return { "M", "pmos", "", 9 }; + case TYPE::NMOS_B4SOI: return { "M", "nmos", "", 10 }; + case TYPE::PMOS_B4SOI: return { "M", "pmos", "", 10 }; + case TYPE::NMOS_BSIM4: return { "M", "nmos", "", 14 }; + case TYPE::PMOS_BSIM4: return { "M", "pmos", "", 14 }; //case TYPE::NMOS_EKV2_6: return {}; //case TYPE::PMOS_EKV2_6: return {}; //case TYPE::NMOS_PSP: return {}; //case TYPE::PMOS_PSP: return {}; - case TYPE::NMOS_B3SOIFD: return { "M", "NMOS", "", 55 }; - case TYPE::PMOS_B3SOIFD: return { "M", "PMOS", "", 55 }; - case TYPE::NMOS_B3SOIDD: return { "M", "NMOS", "", 56 }; - case TYPE::PMOS_B3SOIDD: return { "M", "PMOS", "", 56 }; - case TYPE::NMOS_B3SOIPD: return { "M", "NMOS", "", 57 }; - case TYPE::PMOS_B3SOIPD: return { "M", "PMOS", "", 57 }; + case TYPE::NMOS_B3SOIFD: return { "M", "nmos", "", 55 }; + case TYPE::PMOS_B3SOIFD: return { "M", "pmos", "", 55 }; + case TYPE::NMOS_B3SOIDD: return { "M", "nmos", "", 56 }; + case TYPE::PMOS_B3SOIDD: return { "M", "pmos", "", 56 }; + case TYPE::NMOS_B3SOIPD: return { "M", "nmos", "", 57 }; + case TYPE::PMOS_B3SOIPD: return { "M", "pmos", "", 57 }; //case TYPE::NMOS_STAG: return {}; //case TYPE::PMOS_STAG: return {}; - case TYPE::NMOS_HISIM2: return { "M", "NMOS", "", 68 }; - case TYPE::PMOS_HISIM2: return { "M", "PMOS", "", 68 }; - case TYPE::NMOS_HISIMHV1: return { "M", "NMOS", "", 73, false, "1.2.4" }; - case TYPE::PMOS_HISIMHV1: return { "M", "PMOS", "", 73, false, "1.2.4" }; - case TYPE::NMOS_HISIMHV2: return { "M", "NMOS", "", 73, false, "2.2.0" }; - case TYPE::PMOS_HISIMHV2: return { "M", "PMOS", "", 73, false, "2.2.0" }; + case TYPE::NMOS_HISIM2: return { "M", "nmos", "", 68 }; + case TYPE::PMOS_HISIM2: return { "M", "pmos", "", 68 }; + case TYPE::NMOS_HISIMHV1: return { "M", "nmos", "", 73, false, "1.2.4" }; + case TYPE::PMOS_HISIMHV1: return { "M", "pmos", "", 73, false, "1.2.4" }; + case TYPE::NMOS_HISIMHV2: return { "M", "nmos", "", 73, false, "2.2.0" }; + case TYPE::PMOS_HISIMHV2: return { "M", "pmos", "", 73, false, "2.2.0" }; case TYPE::V_DC: return { "V", "" }; case TYPE::V_SIN: return { "V", "", "SIN" }; @@ -442,10 +443,10 @@ template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector& aFiel template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector& aFields ) { - wxString typeFieldValue = GetFieldValue( &aFields, TYPE_FIELD ); wxString deviceTypeFieldValue = GetFieldValue( &aFields, DEVICE_TYPE_FIELD ); + wxString typeFieldValue = GetFieldValue( &aFields, TYPE_FIELD ); - if( !typeFieldValue.IsEmpty() ) + if( !deviceTypeFieldValue.IsEmpty() ) { for( TYPE type : TYPE_ITERATOR() ) { @@ -455,26 +456,85 @@ TYPE SIM_MODEL::ReadTypeFromFields( const std::vector& aFields ) return type; } } - - return TYPE::NONE; } + if( !typeFieldValue.IsEmpty() ) + return TYPE::NONE; + // No type information. For passives we infer the model from the mandatory fields in this case. + TYPE typeFromRef = InferTypeFromRef( GetFieldValue( &aFields, REFERENCE_FIELD ) ); + if( typeFromRef != TYPE::NONE ) + return typeFromRef; - wxString ref = GetFieldValue( &aFields, REFERENCE_FIELD ); + // Finally, try to infer the model from legacy fields, if present. + return InferTypeFromLegacyFields( aFields ); +} - if( ref.StartsWith( "R" ) ) - return TYPE::R; - else if( ref.StartsWith( "C" ) ) - return TYPE::C; - else if( ref.StartsWith( "L" ) ) - return TYPE::L; + +TYPE SIM_MODEL::InferTypeFromRef( const wxString& aRef ) +{ + static std::map refPrefixToType = { + { "R", TYPE::R }, + { "C", TYPE::C }, + { "L", TYPE::L }, + { "VDC", TYPE::V_DC }, + { "VSIN", TYPE::V_SIN }, + { "VPULSE", TYPE::V_PULSE }, + { "VEXP", TYPE::V_EXP }, + { "VSFAM", TYPE::V_SFAM }, + { "VSFFM", TYPE::V_SFFM }, + { "VPWL", TYPE::V_PWL }, + { "VWHITENOISE", TYPE::V_WHITENOISE }, + { "VPINKNOISE", TYPE::V_PINKNOISE }, + { "VBURSTNOISE", TYPE::V_BURSTNOISE }, + { "VRANDUNIFORM", TYPE::V_RANDUNIFORM }, + { "VRANDNORMAL", TYPE::V_RANDNORMAL }, + { "VRANDEXP", TYPE::V_RANDEXP }, + { "VRANDPOISSON", TYPE::V_RANDPOISSON }, + { "VBEHAVIORAL", TYPE::V_BEHAVIORAL }, + { "IDC", TYPE::I_DC }, + { "ISIN", TYPE::I_SIN }, + { "IPULSE", TYPE::I_PULSE }, + { "IEXP", TYPE::I_EXP }, + { "ISFAM", TYPE::I_SFAM }, + { "ISFFM", TYPE::I_SFFM }, + { "IPWL", TYPE::I_PWL }, + { "IWHITENOISE", TYPE::I_WHITENOISE }, + { "IPINKNOISE", TYPE::I_PINKNOISE }, + { "IBURSTNOISE", TYPE::I_BURSTNOISE }, + { "IRANDUNIFORM", TYPE::I_RANDUNIFORM }, + { "IRANDNORMAL", TYPE::I_RANDNORMAL }, + { "IRANDEXP", TYPE::I_RANDEXP }, + { "IRANDPOISSON", TYPE::I_RANDPOISSON }, + { "IBEHAVIORAL", TYPE::I_BEHAVIORAL } + }; + + for( auto&& [prefix, type] : refPrefixToType ) + { + if( aRef.StartsWith( prefix ) ) + return type; + } return TYPE::NONE; } -std::unique_ptr SIM_MODEL::Create( TYPE aType, int aSymbolPinCount ) +template +TYPE SIM_MODEL::InferTypeFromLegacyFields( const std::vector& aFields ) +{ + if( !GetFieldValue( &aFields, SIM_MODEL_SPICE::LEGACY_TYPE_FIELD ).IsEmpty() + || !GetFieldValue( &aFields, SIM_MODEL_SPICE::LEGACY_MODEL_FIELD ).IsEmpty() + || !GetFieldValue( &aFields, SIM_MODEL_SPICE::LEGACY_ENABLED_FIELD ).IsEmpty() + || !GetFieldValue( &aFields, SIM_MODEL_SPICE::LEGACY_LIB_FIELD ).IsEmpty() ) + { + return TYPE::SPICE; + } + else + return TYPE::NONE; +} + + +std::unique_ptr SIM_MODEL::Create( TYPE aType, unsigned aSymbolPinCount ) { std::unique_ptr model = create( aType ); @@ -502,15 +562,15 @@ std::unique_ptr SIM_MODEL::Create( const std::string& aSpiceCode ) template std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, - int aSymbolPinCount, + unsigned aSymbolPinCount, const std::vector& aFields ); template std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, - int aSymbolPinCount, + unsigned aSymbolPinCount, const std::vector& aFields ); template -std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, int aSymbolPinCount, +std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount, const std::vector& aFields ) { std::unique_ptr model = create( aBaseModel.GetType() ); @@ -521,13 +581,14 @@ std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, int a } -template std::unique_ptr SIM_MODEL::Create( int aSymbolPinCount, +template std::unique_ptr SIM_MODEL::Create( unsigned aSymbolPinCount, const std::vector& aFields ); -template std::unique_ptr SIM_MODEL::Create( int aSymbolPinCount, +template std::unique_ptr SIM_MODEL::Create( unsigned aSymbolPinCount, const std::vector& aFields ); template -std::unique_ptr SIM_MODEL::Create( int aSymbolPinCount, const std::vector& aFields ) +std::unique_ptr SIM_MODEL::Create( unsigned aSymbolPinCount, + const std::vector& aFields ) { std::unique_ptr model = SIM_MODEL::create( ReadTypeFromFields( aFields ) ); @@ -608,10 +669,10 @@ bool SIM_MODEL::ReadSpiceCode( const std::string& aSpiceCode ) { // The default behavior is to treat the Spice param=value pairs as the model parameters and // values (for many models the correspondence is not exact, so this function is overridden). - + tao::pegtl::string_input<> in( aSpiceCode, "from_content" ); std::unique_ptr root; - + try { root = tao::pegtl::parse_tree::parsestring() ) ) + if( !SetParamFromSpiceCode( paramName, subnode->string() ) ) return false; } else @@ -680,59 +742,59 @@ bool SIM_MODEL::ReadSpiceCode( const std::string& aSpiceCode ) template -void SIM_MODEL::ReadDataFields( int aSymbolPinCount, const std::vector* aFields ) +void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) { doReadDataFields( aSymbolPinCount, aFields ); } template <> -void SIM_MODEL::ReadDataFields( int aSymbolPinCount, const std::vector* aFields ) +void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) { ReadDataSchFields( aSymbolPinCount, aFields ); } template <> -void SIM_MODEL::ReadDataFields( int aSymbolPinCount, const std::vector* aFields ) +void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) { ReadDataLibFields( aSymbolPinCount, aFields ); } -void SIM_MODEL::ReadDataSchFields( int aSymbolPinCount, const std::vector* aFields ) +void SIM_MODEL::ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) { doReadDataFields( aSymbolPinCount, aFields ); } -void SIM_MODEL::ReadDataLibFields( int aSymbolPinCount, const std::vector* aFields ) +void SIM_MODEL::ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ) { doReadDataFields( aSymbolPinCount, aFields ); } template <> -void SIM_MODEL::WriteFields( std::vector& aFields ) +void SIM_MODEL::WriteFields( std::vector& aFields ) const { WriteDataSchFields( aFields ); } template <> -void SIM_MODEL::WriteFields( std::vector& aFields ) +void SIM_MODEL::WriteFields( std::vector& aFields ) const { WriteDataLibFields( aFields ); } -void SIM_MODEL::WriteDataSchFields( std::vector& aFields ) +void SIM_MODEL::WriteDataSchFields( std::vector& aFields ) const { doWriteFields( aFields ); } -void SIM_MODEL::WriteDataLibFields( std::vector& aFields ) +void SIM_MODEL::WriteDataLibFields( std::vector& aFields ) const { doWriteFields( aFields ); } @@ -750,7 +812,7 @@ wxString SIM_MODEL::GenerateSpiceModelLine( const wxString& aModelName ) const line << wxString::Format( ".model %s %s(\n+", aModelName, GetSpiceInfo().modelType ); - for( int paramIndex = 0; paramIndex < GetParamCount(); ++paramIndex ) + for( unsigned paramIndex = 0; paramIndex < GetParamCount(); ++paramIndex ) { const PARAM& param = GetParam( paramIndex ); wxString valueStr = param.value->ToString(); @@ -776,10 +838,10 @@ wxString SIM_MODEL::GenerateSpiceModelLine( const wxString& aModelName ) const wxString SIM_MODEL::GenerateSpiceItemName( const wxString& aRefName ) const { - if( !aRefName.IsEmpty() && aRefName.StartsWith( GetSpiceInfo().primitive ) ) + if( !aRefName.IsEmpty() && aRefName.StartsWith( GetSpiceInfo().itemType ) ) return aRefName; else - return GetSpiceInfo().primitive + aRefName; + return GetSpiceInfo().itemType + aRefName; } @@ -797,23 +859,21 @@ wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName, wxString result = ""; result << GenerateSpiceItemName( aRefName ) << " "; - for( int i = 0; i < GetPinCount(); ++i ) + for( const PIN& pin : GetPins() ) { - for( int j = 0; j < ( int ) aPinNetNames.size(); ++j ) + for( unsigned i = 0; i < aPinNetNames.size(); ++i ) { - int symbolPinNumber = j + 1; - - if( symbolPinNumber == GetPin( i ).symbolPinNumber ) - result << aPinNetNames[j] << " "; + unsigned symbolPinNumber = i + 1; + + if( symbolPinNumber == pin.symbolPinNumber ) + result << aPinNetNames[i] << " "; } } result << aModelName << " "; - for( int i = 0; i < GetParamCount(); ++i ) + for( const PARAM& param : GetParams() ) { - const PARAM& param = GetParam( i ); - if( param.info.isInstanceParam ) result << param.info.name << "=" << param.value->ToString() << " "; } @@ -860,63 +920,15 @@ std::vector SIM_MODEL::GenerateSpiceCurrentNames( const wxString& aRef } -bool SIM_MODEL::ParsePinsField( int aSymbolPinCount, const wxString& aPinsField ) -{ - // Default pin sequence: model pins are the same as symbol pins. - // Excess model pins are set as Not Connected. - for( int i = 0; i < static_cast( getPinNames().size() ); ++i ) - { - if( i < aSymbolPinCount ) - AddPin( { getPinNames().at( i ), i + 1 } ); - else - AddPin( { getPinNames().at( i ), PIN::NOT_CONNECTED } ); - } - - if( aPinsField.IsEmpty() ) - return true; - - LOCALE_IO toggle; - - tao::pegtl::string_input<> in( aPinsField.ToStdString(), "from_content" ); - std::unique_ptr root; - - try - { - root = tao::pegtl::parse_tree::parse( in ); - } - catch( const tao::pegtl::parse_error& e ) - { - return false; - } - - wxASSERT( root ); - - if( static_cast( root->children.size() ) != GetPinCount() ) - return false; - - for( unsigned int i = 0; i < root->children.size(); ++i ) - { - if( root->children.at( i )->string() == "X" ) - SetPinSymbolPinNumber( static_cast( i ), PIN::NOT_CONNECTED ); - else - SetPinSymbolPinNumber( static_cast( i ), - std::stoi( root->children.at( i )->string() ) ); - } - - return true; -} - - void SIM_MODEL::AddPin( const PIN& aPin ) { m_pins.push_back( aPin ); } -int SIM_MODEL::FindModelPinNumber( int aSymbolPinNumber ) +unsigned SIM_MODEL::FindModelPinNumber( unsigned aSymbolPinNumber ) { - for( int i = 0; i < GetPinCount(); ++i ) + for( unsigned i = 0; i < GetPinCount(); ++i ) { if( GetPin( i ).symbolPinNumber == aSymbolPinNumber ) return i + 1; @@ -932,7 +944,18 @@ void SIM_MODEL::AddParam( const PARAM::INFO& aInfo, bool aIsOtherVariant ) } -const SIM_MODEL::PARAM& SIM_MODEL::GetParam( int aParamIndex ) const +std::vector> SIM_MODEL::GetPins() const +{ + std::vector> pins; + + for( unsigned i = 0; i < GetPinCount(); ++i ) + pins.emplace_back( GetPin( i ) ); + + return pins; +} + + +const SIM_MODEL::PARAM& SIM_MODEL::GetParam( unsigned aParamIndex ) const { if( m_baseModel && m_params.at( aParamIndex ).value->ToString().IsEmpty() ) return m_baseModel->GetParam( aParamIndex ); @@ -941,13 +964,24 @@ const SIM_MODEL::PARAM& SIM_MODEL::GetParam( int aParamIndex ) const } -const SIM_MODEL::PARAM& SIM_MODEL::GetUnderlyingParam( int aParamIndex ) const +std::vector> SIM_MODEL::GetParams() const +{ + std::vector> params; + + for( unsigned i = 0; i < GetParamCount(); ++i ) + params.emplace_back( GetParam( i ) ); + + return params; +} + + +const SIM_MODEL::PARAM& SIM_MODEL::GetUnderlyingParam( unsigned aParamIndex ) const { return m_params.at( aParamIndex ); } -const SIM_MODEL::PARAM& SIM_MODEL::GetBaseParam( int aParamIndex ) const +const SIM_MODEL::PARAM& SIM_MODEL::GetBaseParam( unsigned aParamIndex ) const { if( m_baseModel ) return m_baseModel->GetParam( aParamIndex ); @@ -956,7 +990,7 @@ const SIM_MODEL::PARAM& SIM_MODEL::GetBaseParam( int aParamIndex ) const } -bool SIM_MODEL::SetParamValue( int aParamIndex, const wxString& aValue, +bool SIM_MODEL::SetParamValue( unsigned aParamIndex, const wxString& aValue, SIM_VALUE_GRAMMAR::NOTATION aNotation ) { // Models sourced from a library are immutable. @@ -999,6 +1033,191 @@ SIM_MODEL::SIM_MODEL( TYPE aType ) : m_baseModel( nullptr ), m_type( aType ) } +template void SIM_MODEL::WriteInferredDataFields( std::vector& aFields, + const wxString& aValue ) const; +template void SIM_MODEL::WriteInferredDataFields( std::vector& aFields, + const wxString& aValue ) const; + +template +void SIM_MODEL::WriteInferredDataFields( std::vector& aFields, const wxString& aValue ) const +{ + if( GetPinCount() == 2 + && GetPin( 0 ).symbolPinNumber == 1 + && GetPin( 1 ).symbolPinNumber == 2 ) + { + SetFieldValue( aFields, PINS_FIELD, "" ); + } + + SetFieldValue( aFields, VALUE_FIELD, aValue ); + SetFieldValue( aFields, DEVICE_TYPE_FIELD, "" ); + SetFieldValue( aFields, TYPE_FIELD, "" ); + SetFieldValue( aFields, PARAMS_FIELD, "" ); +} + + +wxString SIM_MODEL::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const +{ + wxString result = ""; + + if( aIsFirst ) + aIsFirst = false; + else + result << " "; + + result << aParam.info.name + "=" + aParam.value->ToString(); + return result; +} + + +wxString SIM_MODEL::GenerateParamsField( const wxString& aPairSeparator ) const +{ + bool isFirst = true; + wxString result = ""; + + for( const PARAM& param : m_params ) + { + wxString valueStr = param.value->ToString(); + + if( valueStr.IsEmpty() ) + continue; + + result << GenerateParamValuePair( param, isFirst ); + } + + return result; +} + + +bool SIM_MODEL::ParseParamsField( const wxString& aParamsField ) +{ + LOCALE_IO toggle; + + tao::pegtl::string_input<> in( aParamsField.ToStdString(), "from_content" ); + std::unique_ptr root; + + try + { + // Using parse tree instead of actions because we don't care about performance that much, + // and having a tree greatly simplifies some things. + root = tao::pegtl::parse_tree::parse< + SIM_MODEL_PARSER::fieldParamValuePairsGrammar, + SIM_MODEL_PARSER::fieldParamValuePairsSelector> + ( in ); + } + catch( const tao::pegtl::parse_error& e ) + { + return false; + } + + wxASSERT( root ); + + wxString paramName = ""; + + for( const auto& node : root->children ) + { + if( node->is_type() ) + paramName = node->string(); + // TODO: Do something with number. + // It doesn't seem too useful? + else if( node->is_type>() + || node->is_type>() + || node->is_type() ) + { + wxASSERT( !paramName.IsEmpty() ); + // TODO: Shouldn't be named "...fromSpiceCode" here... + + SetParamFromSpiceCode( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI ); + } + else if( node->is_type() ) + { + wxASSERT( !paramName.IsEmpty() ); + + wxString str = node->string(); + + // Unescape quotes. + str.Replace( "\\\"", "\"" ); + + SetParamFromSpiceCode( paramName, str, SIM_VALUE_GRAMMAR::NOTATION::SI ); + } + else + { + wxFAIL; + return false; + } + } + + return true; +} + + +bool SIM_MODEL::ParsePinsField( unsigned aSymbolPinCount, const wxString& aPinsField ) +{ + // Default pin sequence: model pins are the same as symbol pins. + // Excess model pins are set as Not Connected. + for( unsigned i = 0; i < getPinNames().size(); ++i ) + { + if( i < aSymbolPinCount ) + AddPin( { getPinNames().at( i ), i + 1 } ); + else + AddPin( { getPinNames().at( i ), PIN::NOT_CONNECTED } ); + } + + if( aPinsField.IsEmpty() ) + return true; + + LOCALE_IO toggle; + + tao::pegtl::string_input<> in( aPinsField.ToStdString(), "from_content" ); + std::unique_ptr root; + + try + { + root = tao::pegtl::parse_tree::parse( in ); + } + catch( const tao::pegtl::parse_error& e ) + { + return false; + } + + wxASSERT( root ); + + if( root->children.size() != GetPinCount() ) + return false; + + for( unsigned i = 0; i < root->children.size(); ++i ) + { + if( root->children.at( i )->string() == "X" ) + SetPinSymbolPinNumber( static_cast( i ), PIN::NOT_CONNECTED ); + else + SetPinSymbolPinNumber( static_cast( i ), + std::stoi( root->children.at( i )->string() ) ); + } + + return true; +} + + +bool SIM_MODEL::SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation ) +{ + std::vector> params = GetParams(); + + auto it = std::find_if( params.begin(), params.end(), + [aParamName]( const PARAM& param ) + { + return param.info.name == aParamName.Lower(); + } ); + + if( it == params.end() ) + return false; + + return SetParamValue( it - params.begin(), aParamValue, aNotation ); +} + + std::unique_ptr SIM_MODEL::create( TYPE aType ) { switch( aType ) @@ -1008,6 +1227,11 @@ std::unique_ptr SIM_MODEL::create( TYPE aType ) case TYPE::L: return std::make_unique( aType ); + case TYPE::R_ADV: + case TYPE::C_ADV: + case TYPE::L_ADV: + return std::make_unique( aType ); + case TYPE::R_BEHAVIORAL: case TYPE::C_BEHAVIORAL: case TYPE::L_BEHAVIORAL: @@ -1052,7 +1276,7 @@ std::unique_ptr SIM_MODEL::create( TYPE aType ) return std::make_unique( aType ); case TYPE::SPICE: - return std::make_unique( aType ); + return std::make_unique( aType ); default: return std::make_unique( aType ); @@ -1062,9 +1286,19 @@ std::unique_ptr SIM_MODEL::create( TYPE aType ) TYPE SIM_MODEL::readTypeFromSpiceTypeString( const std::string& aTypeString ) { + std::string lowercaseTypeString = aTypeString; + std::transform( lowercaseTypeString.begin(), lowercaseTypeString.end(), + lowercaseTypeString.begin(), ::tolower ); + for( TYPE type : TYPE_ITERATOR() ) { - if( SpiceInfo( type ).modelType == aTypeString ) + wxString typePrefix = SpiceInfo( type ).modelType; + + if( typePrefix == "" ) + continue; + + // Check if `aTypeString` starts with `typePrefix`. + if( lowercaseTypeString.rfind( typePrefix, 0 ) == 0 ) return type; } @@ -1075,20 +1309,20 @@ TYPE SIM_MODEL::readTypeFromSpiceTypeString( const std::string& aTypeString ) template -void SIM_MODEL::doReadDataFields( int aSymbolPinCount, const std::vector* aFields ) +void SIM_MODEL::doReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) { ParsePinsField( aSymbolPinCount, GetFieldValue( aFields, PINS_FIELD ) ); - parseParamsField( GetFieldValue( aFields, PARAMS_FIELD ) ); + ParseParamsField( GetFieldValue( aFields, PARAMS_FIELD ) ); } template -void SIM_MODEL::doWriteFields( std::vector& aFields ) +void SIM_MODEL::doWriteFields( std::vector& aFields ) const { SetFieldValue( aFields, DEVICE_TYPE_FIELD, generateDeviceTypeField() ); SetFieldValue( aFields, TYPE_FIELD, generateTypeField() ); SetFieldValue( aFields, PINS_FIELD, generatePinsField() ); - SetFieldValue( aFields, PARAMS_FIELD, generateParamsField( " " ) ); + SetFieldValue( aFields, PARAMS_FIELD, GenerateParamsField( " " ) ); } @@ -1109,7 +1343,7 @@ wxString SIM_MODEL::generatePinsField() const wxString result = ""; bool isFirst = true; - for( int i = 0; i < GetPinCount(); ++i ) + for( unsigned i = 0; i < GetPinCount(); ++i ) { if( isFirst ) isFirst = false; @@ -1124,96 +1358,3 @@ wxString SIM_MODEL::generatePinsField() const return result; } - - -wxString SIM_MODEL::generateParamsField( const wxString& aPairSeparator ) const -{ - bool isFirst = true; - wxString result = ""; - - for( const PARAM& param : m_params ) - { - wxString valueStr = param.value->ToString(); - - if( valueStr.IsEmpty() ) - continue; - - if( isFirst ) - isFirst = false; - else - result << " "; - - result << param.info.name; - result << "="; - result << param.value->ToString(); - } - - return result; -} - - -bool SIM_MODEL::parseParamsField( const wxString& aParamsField ) -{ - LOCALE_IO toggle; - - tao::pegtl::string_input<> in( aParamsField.ToStdString(), "from_content" ); - std::unique_ptr root; - - try - { - // Using parse tree instead of actions because we don't care about performance that much, - // and having a tree greatly simplifies some things. - root = tao::pegtl::parse_tree::parse< - SIM_MODEL_PARSER::paramValuePairsGrammar, - SIM_MODEL_PARSER::paramValuePairsSelector> - ( in ); - } - catch( const tao::pegtl::parse_error& e ) - { - return false; - } - - wxASSERT( root ); - - wxString paramName = ""; - - for( const auto& node : root->children ) - { - if( node->is_type() ) - paramName = node->string(); - // TODO: Do something with number. - // It doesn't seem too useful? - else if( node->is_type>() ) - { - wxASSERT( !paramName.IsEmpty() ); - // TODO: Shouldn't be named "...fromSpiceCode" here... - setParamFromSpiceCode( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI ); - } - else - { - wxFAIL; - return false; - } - } - - return true; -} - - -bool SIM_MODEL::setParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, - SIM_VALUE_GRAMMAR::NOTATION aNotation ) -{ - int i = 0; - - for(; i < GetParamCount(); ++i ) - { - if( GetParam( i ).info.name == aParamName.Lower() ) - break; - } - - if( i == GetParamCount() ) - return false; // No parameter with this name exists. - - return SetParamValue( i, wxString( aParamValue ), aNotation ); -} diff --git a/eeschema/sim/sim_model.h b/eeschema/sim/sim_model.h index 7c27fe6d64..17d28f3791 100644 --- a/eeschema/sim/sim_model.h +++ b/eeschema/sim/sim_model.h @@ -31,7 +31,6 @@ #include #include #include -#include class SIM_LIBRARY; @@ -40,6 +39,8 @@ namespace SIM_MODEL_GRAMMAR { using namespace SPICE_GRAMMAR; + struct sep : plus {}; + struct pinNumber : sor> {}; struct pinSequence : seq, eof> {}; - template - struct paramValuePairsGrammar : must, - paramValuePairs, - opt, - eof> {}; + struct unquotedString : plus, any> {}; + struct quotedString : seq, + until>, + one<'"'>>>> {}; + + struct fieldParamValuePair : seq, + one<'='>, + opt, + sor, + number, + quotedString, + unquotedString>> {}; + + struct fieldParamValuePairs : seq, + star> {}; + + struct fieldParamValuePairsGrammar : must, + fieldParamValuePairs, + opt, + eof> {}; } @@ -270,7 +289,7 @@ public: struct SPICE_INFO { - wxString primitive; + wxString itemType; wxString modelType = ""; wxString inlineTypeString = ""; int level = 0; @@ -284,7 +303,7 @@ public: static constexpr auto NOT_CONNECTED = 0; const wxString name; - int symbolPinNumber; + unsigned symbolPinNumber; }; @@ -318,14 +337,14 @@ public: struct INFO { wxString name; - unsigned int id = 0; // Legacy. + unsigned id = 0; // Legacy (don't remove). DIR dir = DIR::INOUT; SIM_VALUE::TYPE type = SIM_VALUE::TYPE::FLOAT; - FLAGS flags = {}; // Legacy + FLAGS flags = {}; // Legacy (don't remove). wxString unit = ""; CATEGORY category = CATEGORY::PRINCIPAL; wxString defaultValue = ""; - wxString defaultValueOfOtherVariant = ""; // Legacy. + wxString defaultValueOfOtherVariant = ""; // Legacy (don't remove). wxString description = ""; bool isInstanceParam = false; }; @@ -352,16 +371,22 @@ public: template static TYPE ReadTypeFromFields( const std::vector& aFields ); + static TYPE InferTypeFromRef( const wxString& aRef ); - static std::unique_ptr Create( TYPE aType, int aSymbolPinCount = 0 ); + template + static TYPE InferTypeFromLegacyFields( const std::vector& aFields ); + + + static std::unique_ptr Create( TYPE aType, unsigned aSymbolPinCount = 0 ); static std::unique_ptr Create( const std::string& aSpiceCode ); template - static std::unique_ptr Create( const SIM_MODEL& aBaseModel, int aSymbolPinCount, + static std::unique_ptr Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount, const std::vector& aFields ); template - static std::unique_ptr Create( int aSymbolPinCount, const std::vector& aFields ); + static std::unique_ptr Create( unsigned aSymbolPinCount, + const std::vector& aFields ); template static wxString GetFieldValue( const std::vector* aFields, const wxString& aFieldName ); @@ -383,19 +408,19 @@ public: virtual bool ReadSpiceCode( const std::string& aSpiceCode ); template - void ReadDataFields( int aSymbolPinCount, const std::vector* aFields ); + void ReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); // C++ doesn't allow virtual template methods, so we do this: - virtual void ReadDataSchFields( int aSymbolPinCount, const std::vector* aFields ); - virtual void ReadDataLibFields( int aSymbolPinCount, const std::vector* aFields ); + virtual void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ); + virtual void ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ); template - void WriteFields( std::vector& aFields ); + void WriteFields( std::vector& aFields ) const; // C++ doesn't allow virtual template methods, so we do this: - virtual void WriteDataSchFields( std::vector& aFields ); - virtual void WriteDataLibFields( std::vector& aFields ); + virtual void WriteDataSchFields( std::vector& aFields ) const; + virtual void WriteDataLibFields( std::vector& aFields ) const; virtual bool HasToIncludeSpiceLibrary() const { return GetBaseModel() && !HasOverrides(); } @@ -415,10 +440,8 @@ public: SPICE_INFO GetSpiceInfo() const; virtual std::vector GenerateSpiceCurrentNames( const wxString& aRefName ) const; - bool ParsePinsField( int aSymbolPinCount, const wxString& aPinsField ); - void AddPin( const PIN& aPin ); - int FindModelPinNumber( int aSymbolPinNumber ); + unsigned FindModelPinNumber( unsigned aSymbolPinNumber ); void AddParam( const PARAM::INFO& aInfo, bool aIsOtherVariant = false ); DEVICE_TYPE GetDeviceType() const { return TypeInfo( GetType() ).deviceType; } @@ -427,8 +450,10 @@ public: const SIM_MODEL* GetBaseModel() const { return m_baseModel; } virtual void SetBaseModel( const SIM_MODEL& aBaseModel ) { m_baseModel = &aBaseModel; } - int GetPinCount() const { return static_cast( m_pins.size() ); } - const PIN& GetPin( int aIndex ) const { return m_pins.at( aIndex ); } + unsigned GetPinCount() const { return m_pins.size(); } + const PIN& GetPin( unsigned aIndex ) const { return m_pins.at( aIndex ); } + + std::vector> GetPins() const; void SetPinSymbolPinNumber( int aIndex, int aSymbolPinNumber ) { @@ -436,11 +461,14 @@ public: } - int GetParamCount() const { return static_cast( m_params.size() ); } - const PARAM& GetParam( int aParamIndex ) const; // Return base parameter unless it's overridden. - const PARAM& GetUnderlyingParam( int aParamIndex ) const; // Return the actual parameter. - const PARAM& GetBaseParam( int aParamIndex ) const; // Always return base parameter if it exists. - virtual bool SetParamValue( int aParamIndex, const wxString& aValue, + unsigned GetParamCount() const { return m_params.size(); } + const PARAM& GetParam( unsigned aParamIndex ) const; // Return base parameter unless it's overridden. + + std::vector> GetParams() const; + + const PARAM& GetUnderlyingParam( unsigned aParamIndex ) const; // Return the actual parameter. + const PARAM& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists. + virtual bool SetParamValue( unsigned aParamIndex, const wxString& aValue, SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI ); @@ -450,10 +478,28 @@ public: // Can modifying a model parameter also modify other parameters? virtual bool HasAutofill() const { return false; } + wxString GetErrorMessage() { return m_errorMessage; } + protected: SIM_MODEL( TYPE aType ); + template + void WriteInferredDataFields( std::vector& aFields, const wxString& aValue ) const; + + virtual wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const; + + wxString GenerateParamsField( const wxString& aPairSeparator ) const; + bool ParseParamsField( const wxString& aParamsField ); + + bool ParsePinsField( unsigned aSymbolPinCount, const wxString& aPinsField ); + + // TODO: Rename. + virtual bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation + = SIM_VALUE_GRAMMAR::NOTATION::SPICE ); + wxString m_spiceCode; + wxString m_errorMessage; private: static std::unique_ptr create( TYPE aType ); @@ -461,10 +507,10 @@ private: template - void doReadDataFields( int aSymbolPinCount, const std::vector* aFields ); + void doReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); template - void doWriteFields( std::vector& aFields ); + void doWriteFields( std::vector& aFields ) const; virtual std::vector getPinNames() const { return {}; } @@ -474,15 +520,6 @@ private: wxString generatePinsField() const; - - wxString generateParamsField( const wxString& aPairSeparator ) const; - bool parseParamsField( const wxString& aParamsField ); - - // TODO: Rename. - virtual bool setParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, - SIM_VALUE_GRAMMAR::NOTATION aNotation - = SIM_VALUE_GRAMMAR::NOTATION::SPICE ); - const SIM_MODEL* m_baseModel; diff --git a/eeschema/sim/sim_model_behavioral.cpp b/eeschema/sim/sim_model_behavioral.cpp index b9f001a346..e81cdb6e13 100644 --- a/eeschema/sim/sim_model_behavioral.cpp +++ b/eeschema/sim/sim_model_behavioral.cpp @@ -29,11 +29,11 @@ SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) : SIM_MODEL( aType ) { - static PARAM::INFO resistor = makeParamInfo( "r", "Expression for resistance", "ohm" ); - static PARAM::INFO capacitor = makeParamInfo( "c", "Expression for capacitance", "F" ); - static PARAM::INFO inductor = makeParamInfo( "l", "Expression for inductance", "H" ); - static PARAM::INFO vsource = makeParamInfo( "v", "Expression for voltage", "V" ); - static PARAM::INFO isource = makeParamInfo( "i", "Expression for current", "A" ); + static PARAM::INFO resistor = makeParams( "r", "Expression for resistance", "ohm" ); + static PARAM::INFO capacitor = makeParams( "c", "Expression for capacitance", "F" ); + static PARAM::INFO inductor = makeParams( "l", "Expression for inductance", "H" ); + static PARAM::INFO vsource = makeParams( "v", "Expression for voltage", "V" ); + static PARAM::INFO isource = makeParams( "i", "Expression for current", "A" ); switch( aType ) { @@ -84,16 +84,16 @@ wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceItemLine( const wxString& aRefName, } -SIM_MODEL::PARAM::INFO SIM_MODEL_BEHAVIORAL::makeParamInfo( wxString name, wxString description, - wxString unit ) +SIM_MODEL::PARAM::INFO SIM_MODEL_BEHAVIORAL::makeParams( wxString aName, wxString aDescription, + wxString aUnit ) { - SIM_MODEL::PARAM::INFO paramInfo = {}; + PARAM::INFO paramInfo = {}; - paramInfo.name = name; + paramInfo.name = aName; paramInfo.type = SIM_VALUE::TYPE::FLOAT; - paramInfo.unit = unit; - paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL; - paramInfo.description = description; + paramInfo.unit = aUnit; + paramInfo.category = PARAM::CATEGORY::PRINCIPAL; + paramInfo.description = aDescription; return paramInfo; } diff --git a/eeschema/sim/sim_model_behavioral.h b/eeschema/sim/sim_model_behavioral.h index 9f2798f4bf..021a0a5fe9 100644 --- a/eeschema/sim/sim_model_behavioral.h +++ b/eeschema/sim/sim_model_behavioral.h @@ -42,7 +42,7 @@ public: private: std::vector getPinNames() const override { return { "+", "-" }; } - static PARAM::INFO makeParamInfo( wxString name, wxString description, wxString unit ); + static PARAM::INFO makeParams( wxString aName, wxString aDescription, wxString aUnit ); }; #endif // SIM_MODEL_BEHAVIORAL_H diff --git a/eeschema/sim/sim_model_ideal.cpp b/eeschema/sim/sim_model_ideal.cpp index 569f827a3a..5c6de1ef12 100644 --- a/eeschema/sim/sim_model_ideal.cpp +++ b/eeschema/sim/sim_model_ideal.cpp @@ -28,7 +28,8 @@ using PARAM = SIM_MODEL::PARAM; SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) - : SIM_MODEL( aType ) + : SIM_MODEL( aType ), + m_isInferred( false ) { static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "ohm" ); static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" ); @@ -36,40 +37,50 @@ SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) switch( aType ) { - case TYPE::R: AddParam( resistor ); break; + case TYPE::R: AddParam( resistor ); break; case TYPE::C: AddParam( capacitor ); break; - case TYPE::L: AddParam( inductor ); break; + case TYPE::L: AddParam( inductor ); break; default: wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" ); } } -void SIM_MODEL_IDEAL::ReadDataSchFields( int aSymbolPinCount, +void SIM_MODEL_IDEAL::ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) { if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() ) SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields ); else - { - // Inferred model. - ParsePinsField( aSymbolPinCount, PINS_FIELD ); - SetParamValue( 0, GetFieldValue( aFields, VALUE_FIELD ) ); - } + inferredReadDataFields( aSymbolPinCount, aFields ); } -void SIM_MODEL_IDEAL::ReadDataLibFields( int aSymbolPinCount, +void SIM_MODEL_IDEAL::ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ) { if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() ) SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields ); else - { - // Inferred model. - ParsePinsField( aSymbolPinCount, PINS_FIELD ); - SetParamValue( 0, GetFieldValue( aFields, VALUE_FIELD ) ); - } + inferredReadDataFields( aSymbolPinCount, aFields ); +} + + +void SIM_MODEL_IDEAL::WriteDataSchFields( std::vector& aFields ) const +{ + SIM_MODEL::WriteDataSchFields( aFields ); + + if( m_isInferred ) + inferredWriteDataFields( aFields ); +} + + +void SIM_MODEL_IDEAL::WriteDataLibFields( std::vector& aFields ) const +{ + SIM_MODEL::WriteDataLibFields( aFields ); + + if( m_isInferred ) + inferredWriteDataFields( aFields ); } @@ -83,11 +94,38 @@ wxString SIM_MODEL_IDEAL::GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName, const std::vector& aPinNetNames ) const { - return SIM_MODEL::GenerateSpiceItemLine( aRefName, GetParam( 0 ).value->ToString(), + return SIM_MODEL::GenerateSpiceItemLine( aRefName, + GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE ), aPinNetNames ); } +template +void SIM_MODEL_IDEAL::inferredReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) +{ + ParsePinsField( aSymbolPinCount, PINS_FIELD ); + + if( ( InferTypeFromRef( GetFieldValue( aFields, REFERENCE_FIELD ) ) == GetType() + && SetParamValue( 0, GetFieldValue( aFields, VALUE_FIELD ) ) ) + || GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue ) + { + m_isInferred = true; + } +} + + +template +void SIM_MODEL_IDEAL::inferredWriteDataFields( std::vector& aFields ) const +{ + wxString value = GetParam( 0 ).value->ToString(); + + if( value.IsEmpty() ) + value = DeviceTypeInfo( GetDeviceType() ).fieldValue; + + WriteInferredDataFields( aFields, value ); +} + + PARAM::INFO SIM_MODEL_IDEAL::makeParamInfo( wxString aName, wxString aDescription, wxString aUnit ) { SIM_MODEL::PARAM::INFO paramInfo = {}; diff --git a/eeschema/sim/sim_model_ideal.h b/eeschema/sim/sim_model_ideal.h index 977c21a3ff..c20f45ba6a 100644 --- a/eeschema/sim/sim_model_ideal.h +++ b/eeschema/sim/sim_model_ideal.h @@ -33,8 +33,11 @@ class SIM_MODEL_IDEAL : public SIM_MODEL public: SIM_MODEL_IDEAL( TYPE aType ); - void ReadDataSchFields( int aSymbolPinCount, const std::vector* aFields ) override; - void ReadDataLibFields( int aSymbolPinCount, const std::vector* aFields ) override; + void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; + void ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; + + 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, @@ -43,9 +46,17 @@ public: private: + template + void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); + + template + void inferredWriteDataFields( std::vector& aFields ) const; + std::vector getPinNames() const override { return { "+", "-" }; } static PARAM::INFO makeParamInfo( wxString aName, wxString aDescription, wxString aUnit ); + + bool m_isInferred; }; #endif // SIM_MODEL_IDEAL_H diff --git a/eeschema/sim/sim_model_ngspice.cpp b/eeschema/sim/sim_model_ngspice.cpp index a427347227..d44a960ccd 100644 --- a/eeschema/sim/sim_model_ngspice.cpp +++ b/eeschema/sim/sim_model_ngspice.cpp @@ -36,8 +36,8 @@ SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams ) AddParam( paramInfo, getIsOtherVariant() ); - for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams ) - AddParam( paramInfo, getIsOtherVariant() ); + /*for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams ) + AddParam( paramInfo, getIsOtherVariant() );*/ } @@ -76,6 +76,52 @@ std::vector SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxStri } +bool SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation ) +{ + // One Spice param can have multiple names, we need to take this into account. + + std::vector> params = GetParams(); + + auto paramIt = std::find_if( params.begin(), params.end(), + [aParamName]( const PARAM& param ) + { + return param.info.category != PARAM::CATEGORY::SUPERFLUOUS + && param.info.name == aParamName.Lower(); + } ); + + if( paramIt != params.end() ) + return SetParamValue( paramIt - params.begin(), aParamValue, aNotation ); + + + std::vector ngspiceParams = NGSPICE::ModelInfo( getModelType() ).modelParams; + + auto ngspiceParamIt = std::find_if( ngspiceParams.begin(), ngspiceParams.end(), + [aParamName]( const PARAM& param ) + { + return param.info.name == aParamName.Lower(); + } ); + + if( ngspiceParamIt == ngspiceParams.end() ) + return false; + + // We obtain the id of the Ngspice param that is to be set. + unsigned id = ngspiceParamIt->id; + + // Find an actual parameter with the same id. + paramIt = std::find_if( params.begin(), params.end(), + [id]( const PARAM& param ) + { + return param.info.id == id; + } ); + + if( paramIt == params.end() ) + return false; + + return SetParamValue( paramIt - params.begin(), aParamValue, aNotation ); +} + + std::vector SIM_MODEL_NGSPICE::getPinNames() const { return NGSPICE::ModelInfo( getModelType() ).pinNames; @@ -86,24 +132,24 @@ NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() const { switch( GetType() ) { - case TYPE::NONE: return NGSPICE::MODEL_TYPE::NONE; - case TYPE::R_ADV: return NGSPICE::MODEL_TYPE::RESISTOR; - case TYPE::C_ADV: return NGSPICE::MODEL_TYPE::CAPACITOR; - case TYPE::L_ADV: return NGSPICE::MODEL_TYPE::INDUCTOR; - case TYPE::TLINE_LOSSY: return NGSPICE::MODEL_TYPE::LTRA; - case TYPE::TLINE_LOSSLESS: return NGSPICE::MODEL_TYPE::TRANLINE; - case TYPE::TLINE_URC: return NGSPICE::MODEL_TYPE::URC; - //case TYPE::TLINE_KSPICE: return NGSPICE::MODEL_TYPE::TRANSLINE; - case TYPE::SW_V: return NGSPICE::MODEL_TYPE::SWITCH; - case TYPE::SW_I: return NGSPICE::MODEL_TYPE::CSWITCH; - case TYPE::D: return NGSPICE::MODEL_TYPE::DIODE; + case TYPE::NONE: return NGSPICE::MODEL_TYPE::NONE; + //case TYPE::R_ADV: return NGSPICE::MODEL_TYPE::RESISTOR; + //case TYPE::C_ADV: return NGSPICE::MODEL_TYPE::CAPACITOR; + //case TYPE::L_ADV: return NGSPICE::MODEL_TYPE::INDUCTOR; + case TYPE::TLINE_LOSSY: return NGSPICE::MODEL_TYPE::LTRA; + case TYPE::TLINE_LOSSLESS: return NGSPICE::MODEL_TYPE::TRANLINE; + case TYPE::TLINE_URC: return NGSPICE::MODEL_TYPE::URC; + //case TYPE::TLINE_KSPICE: return NGSPICE::MODEL_TYPE::TRANSLINE; + case TYPE::SW_V: return NGSPICE::MODEL_TYPE::SWITCH; + case TYPE::SW_I: return NGSPICE::MODEL_TYPE::CSWITCH; + case TYPE::D: return NGSPICE::MODEL_TYPE::DIODE; case TYPE::NPN_GUMMELPOON: - case TYPE::PNP_GUMMELPOON: return NGSPICE::MODEL_TYPE::BJT; + case TYPE::PNP_GUMMELPOON: return NGSPICE::MODEL_TYPE::BJT; case TYPE::NPN_VBIC: - case TYPE::PNP_VBIC: return NGSPICE::MODEL_TYPE::VBIC; + case TYPE::PNP_VBIC: return NGSPICE::MODEL_TYPE::VBIC; case TYPE::NPN_HICUML2: - case TYPE::PNP_HICUML2: return NGSPICE::MODEL_TYPE::HICUM2; + case TYPE::PNP_HICUML2: return NGSPICE::MODEL_TYPE::HICUM2; case TYPE::NJFET_SHICHMANHODGES: case TYPE::PJFET_SHICHMANHODGES: return NGSPICE::MODEL_TYPE::JFET; @@ -111,46 +157,46 @@ NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() const case TYPE::PJFET_PARKERSKELLERN: return NGSPICE::MODEL_TYPE::JFET2; case TYPE::NMES_STATZ: - case TYPE::PMES_STATZ: return NGSPICE::MODEL_TYPE::MES; + case TYPE::PMES_STATZ: return NGSPICE::MODEL_TYPE::MES; case TYPE::NMES_YTTERDAL: - case TYPE::PMES_YTTERDAL: return NGSPICE::MODEL_TYPE::MESA; + case TYPE::PMES_YTTERDAL: return NGSPICE::MODEL_TYPE::MESA; case TYPE::NMES_HFET1: - case TYPE::PMES_HFET1: return NGSPICE::MODEL_TYPE::HFET1; + case TYPE::PMES_HFET1: return NGSPICE::MODEL_TYPE::HFET1; case TYPE::PMES_HFET2: - case TYPE::NMES_HFET2: return NGSPICE::MODEL_TYPE::HFET2; + case TYPE::NMES_HFET2: return NGSPICE::MODEL_TYPE::HFET2; case TYPE::NMOS_MOS1: - case TYPE::PMOS_MOS1: return NGSPICE::MODEL_TYPE::MOS1; + case TYPE::PMOS_MOS1: return NGSPICE::MODEL_TYPE::MOS1; case TYPE::NMOS_MOS2: - case TYPE::PMOS_MOS2: return NGSPICE::MODEL_TYPE::MOS2; + case TYPE::PMOS_MOS2: return NGSPICE::MODEL_TYPE::MOS2; case TYPE::NMOS_MOS3: - case TYPE::PMOS_MOS3: return NGSPICE::MODEL_TYPE::MOS3; + case TYPE::PMOS_MOS3: return NGSPICE::MODEL_TYPE::MOS3; case TYPE::NMOS_BSIM1: - case TYPE::PMOS_BSIM1: return NGSPICE::MODEL_TYPE::BSIM1; + case TYPE::PMOS_BSIM1: return NGSPICE::MODEL_TYPE::BSIM1; case TYPE::NMOS_BSIM2: - case TYPE::PMOS_BSIM2: return NGSPICE::MODEL_TYPE::BSIM2; + case TYPE::PMOS_BSIM2: return NGSPICE::MODEL_TYPE::BSIM2; case TYPE::NMOS_MOS6: - case TYPE::PMOS_MOS6: return NGSPICE::MODEL_TYPE::MOS6; + case TYPE::PMOS_MOS6: return NGSPICE::MODEL_TYPE::MOS6; case TYPE::NMOS_BSIM3: - case TYPE::PMOS_BSIM3: return NGSPICE::MODEL_TYPE::BSIM3; + case TYPE::PMOS_BSIM3: return NGSPICE::MODEL_TYPE::BSIM3; case TYPE::NMOS_MOS9: - case TYPE::PMOS_MOS9: return NGSPICE::MODEL_TYPE::MOS9; + case TYPE::PMOS_MOS9: return NGSPICE::MODEL_TYPE::MOS9; case TYPE::NMOS_B4SOI: - case TYPE::PMOS_B4SOI: return NGSPICE::MODEL_TYPE::B4SOI; + case TYPE::PMOS_B4SOI: return NGSPICE::MODEL_TYPE::B4SOI; case TYPE::NMOS_BSIM4: - case TYPE::PMOS_BSIM4: return NGSPICE::MODEL_TYPE::BSIM4; + case TYPE::PMOS_BSIM4: return NGSPICE::MODEL_TYPE::BSIM4; case TYPE::NMOS_B3SOIFD: - case TYPE::PMOS_B3SOIFD: return NGSPICE::MODEL_TYPE::B3SOIFD; + case TYPE::PMOS_B3SOIFD: return NGSPICE::MODEL_TYPE::B3SOIFD; case TYPE::NMOS_B3SOIDD: - case TYPE::PMOS_B3SOIDD: return NGSPICE::MODEL_TYPE::B3SOIDD; + case TYPE::PMOS_B3SOIDD: return NGSPICE::MODEL_TYPE::B3SOIDD; case TYPE::NMOS_B3SOIPD: - case TYPE::PMOS_B3SOIPD: return NGSPICE::MODEL_TYPE::B3SOIPD; + case TYPE::PMOS_B3SOIPD: return NGSPICE::MODEL_TYPE::B3SOIPD; case TYPE::NMOS_HISIM2: - case TYPE::PMOS_HISIM2: return NGSPICE::MODEL_TYPE::HISIM2; + case TYPE::PMOS_HISIM2: return NGSPICE::MODEL_TYPE::HISIM2; case TYPE::NMOS_HISIMHV1: - case TYPE::PMOS_HISIMHV1: return NGSPICE::MODEL_TYPE::HISIMHV1; + case TYPE::PMOS_HISIMHV1: return NGSPICE::MODEL_TYPE::HISIMHV1; case TYPE::NMOS_HISIMHV2: - case TYPE::PMOS_HISIMHV2: return NGSPICE::MODEL_TYPE::HISIMHV2; + case TYPE::PMOS_HISIMHV2: return NGSPICE::MODEL_TYPE::HISIMHV2; default: wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_NGSPICE" ); diff --git a/eeschema/sim/sim_model_ngspice.h b/eeschema/sim/sim_model_ngspice.h index c099187333..193b731f61 100644 --- a/eeschema/sim/sim_model_ngspice.h +++ b/eeschema/sim/sim_model_ngspice.h @@ -36,6 +36,9 @@ public: std::vector GenerateSpiceCurrentNames( const wxString& aRefName ) const override; + bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation ) override; + private: std::vector getPinNames() const override; diff --git a/eeschema/sim/sim_model_passive.cpp b/eeschema/sim/sim_model_passive.cpp new file mode 100644 index 0000000000..629d1c6dfd --- /dev/null +++ b/eeschema/sim/sim_model_passive.cpp @@ -0,0 +1,206 @@ +/* + * 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. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +using PARAM = SIM_MODEL::PARAM; + + +SIM_MODEL_PASSIVE::SIM_MODEL_PASSIVE( TYPE aType ) + : SIM_MODEL( aType ) +{ + static std::vector resistor = makeParamInfos( "r", "Resistance", "ohm" ); + static std::vector capacitor = makeParamInfos( "c", "Capacitance", "F" ); + static std::vector inductor = makeParamInfos( "l", "Inductance", "H" ); + + switch( aType ) + { + case TYPE::R_ADV: + for( const PARAM::INFO& paramInfo : resistor ) + AddParam( paramInfo ); + break; + + case TYPE::C_ADV: + for( const PARAM::INFO& paramInfo : capacitor ) + AddParam( paramInfo ); + break; + + case TYPE::L_ADV: + for( const PARAM::INFO& paramInfo : inductor ) + AddParam( paramInfo ); + break; + + default: + wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_PASSIVE" ); + } +} + + +wxString SIM_MODEL_PASSIVE::GenerateSpiceItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aPinNetNames ) const +{ + wxString result = ""; + result << GenerateSpiceItemName( aRefName ) << " "; + + for( const PIN& pin : GetPins() ) + { + for( unsigned i = 0; i < aPinNetNames.size(); ++i ) + { + unsigned symbolPinNumber = i + 1; + + if( symbolPinNumber == pin.symbolPinNumber ) + result << aPinNetNames[i] << " "; + } + } + + // The model name is preceded by the principal value for resistors. + //if( GetType() == TYPE::R_ADV ) + //result << GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE ) << " "; + + result << aModelName << " "; + + for( const PARAM& param : GetParams() ) + { + if( param.info.isInstanceParam ) + result << param.info.name << "=" << param.value->ToString() << " "; + } + + result << "\n"; + return result; +} + + +bool SIM_MODEL_PASSIVE::SetParamFromSpiceCode( const wxString& aParamName, + const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation ) +{ + if( aParamName.Lower() == "tc" ) + return SetParamFromSpiceCode( "tc1", aParamValue, aNotation ); + + switch( GetType() ) + { + case TYPE::R_ADV: + if( aParamName.Lower() == "tc1r" ) + return SIM_MODEL::SetParamFromSpiceCode( "tc1", aParamValue, aNotation ); + + if( aParamName.Lower() == "tc2r" ) + return SIM_MODEL::SetParamFromSpiceCode( "tc2", aParamValue, aNotation ); + + if( aParamName.Lower() == "res" ) + return SIM_MODEL::SetParamFromSpiceCode( "r", aParamValue, aNotation ); + + break; + + case TYPE::C_ADV: + if( aParamName.Lower() == "cap" ) + return SIM_MODEL::SetParamFromSpiceCode( "c", aParamValue, aNotation ); + + break; + + case TYPE::L_ADV: + if( aParamName.Lower() == "ind" ) + return SIM_MODEL::SetParamFromSpiceCode( "l", aParamValue, aNotation ); + + break; + + default: + break; + } + + return SIM_MODEL::SetParamFromSpiceCode( aParamName, aParamValue, aNotation ); +} + + +std::vector SIM_MODEL_PASSIVE::makeParamInfos( wxString aName, + wxString aDescription, + wxString aUnit ) +{ + std::vector paramInfos; + PARAM::INFO paramInfo = {}; + + paramInfo.name = aName; + paramInfo.type = SIM_VALUE::TYPE::FLOAT; + paramInfo.unit = aUnit; + paramInfo.category = PARAM::CATEGORY::PRINCIPAL; + paramInfo.defaultValue = ""; + paramInfo.description = aDescription; + paramInfos.push_back( paramInfo ); + + paramInfo.name = "temp"; + paramInfo.type = SIM_VALUE::TYPE::FLOAT; + paramInfo.unit = "deg C"; + paramInfo.category = PARAM::CATEGORY::PRINCIPAL; + paramInfo.defaultValue = "27"; + paramInfo.description = "Temperature"; + paramInfos.push_back( paramInfo ); + + paramInfo.name = "tnom"; + paramInfo.type = SIM_VALUE::TYPE::FLOAT; + paramInfo.unit = "deg C"; + paramInfo.category = PARAM::CATEGORY::TEMPERATURE; + paramInfo.defaultValue = "27"; + paramInfo.description = "Nominal temperature"; + paramInfos.push_back( paramInfo ); + + paramInfo.name = "tc1"; + paramInfo.type = SIM_VALUE::TYPE::FLOAT; + paramInfo.unit = aUnit; + paramInfo.category = PARAM::CATEGORY::TEMPERATURE; + paramInfo.defaultValue = "0"; + paramInfo.description = "1st order temperature coefficient"; + paramInfos.push_back( paramInfo ); + + paramInfo.name = "tc2"; + paramInfo.type = SIM_VALUE::TYPE::FLOAT; + paramInfo.unit = aUnit; + paramInfo.category = PARAM::CATEGORY::TEMPERATURE; + paramInfo.defaultValue = "0"; + paramInfo.description = "2nd order temperature coefficient"; + paramInfos.push_back( paramInfo ); + + /*if( aName != "l" ) + { + paramInfo.name = "bv_max"; + paramInfo.type = SIM_VALUE::TYPE::FLOAT; + paramInfo.unit = aUnit; + paramInfo.category = PARAM::CATEGORY::LIMITING_VALUES; + paramInfo.defaultValue = ""; + paramInfo.description = "Max. safe operating voltage"; + paramInfos.push_back( paramInfo ); + }*/ + + if( aName == "r" ) + { + paramInfo.name = "noisy"; + paramInfo.type = SIM_VALUE::TYPE::BOOL; + paramInfo.unit = ""; + paramInfo.category = PARAM::CATEGORY::NOISE; + paramInfo.defaultValue = "True"; + paramInfo.description = "Enable thermal noise"; + paramInfos.push_back( paramInfo ); + } + + return paramInfos; +} diff --git a/eeschema/sim/sim_model_passive.h b/eeschema/sim/sim_model_passive.h new file mode 100644 index 0000000000..9e26003c5a --- /dev/null +++ b/eeschema/sim/sim_model_passive.h @@ -0,0 +1,52 @@ +/* + * 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. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef SIM_MODEL_PASSIVE_H +#define SIM_MODEL_PASSIVE_H + +#include + + +class SIM_MODEL_PASSIVE : public SIM_MODEL +{ +public: + SIM_MODEL_PASSIVE( TYPE aType ); + + wxString GenerateSpiceItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aPinNetNames ) const override; + + bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation + = SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override; + +private: + static std::vector makeParamInfos( wxString aName, wxString aDescription, + wxString aUnit ); + + std::vector getPinNames() const override { return { "+", "-" }; } +}; + + +#endif // SIM_MODEL_PASSIVE_H diff --git a/eeschema/sim/sim_model_source.cpp b/eeschema/sim/sim_model_source.cpp index 46c727cc61..5e4aeeda59 100644 --- a/eeschema/sim/sim_model_source.cpp +++ b/eeschema/sim/sim_model_source.cpp @@ -28,13 +28,52 @@ using PARAM = SIM_MODEL::PARAM; SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) - : SIM_MODEL( aType ) + : SIM_MODEL( aType ), + m_isInferred( false ) { - for( const PARAM::INFO& paramInfo : makeParams( aType ) ) + for( const PARAM::INFO& paramInfo : makeParamInfos( aType ) ) AddParam( paramInfo ); } +void SIM_MODEL_SOURCE::ReadDataSchFields( unsigned aSymbolPinCount, + const std::vector* aFields ) +{ + if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() ) + SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields ); + else + inferredReadDataFields( aSymbolPinCount, aFields ); +} + + +void SIM_MODEL_SOURCE::ReadDataLibFields( unsigned aSymbolPinCount, + const std::vector* aFields ) +{ + if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() ) + SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields ); + else + inferredReadDataFields( aSymbolPinCount, aFields ); +} + + +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 { return ""; @@ -47,7 +86,7 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, { wxString argList = ""; - for( int i = 0; i < GetParamCount(); ++i ) + for( unsigned i = 0; i < GetParamCount(); ++i ) argList << GetParam( i ).value->ToString() << " "; wxString model = wxString::Format( GetSpiceInfo().inlineTypeString + "( %s)", argList ); @@ -56,49 +95,49 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, } -const std::vector& SIM_MODEL_SOURCE::makeParams( TYPE aType ) +const std::vector& SIM_MODEL_SOURCE::makeParamInfos( TYPE aType ) { - static std::vector vdc = makeDc( "v", "V" ); - static std::vector idc = makeDc( "i", "A" ); + static std::vector vdc = makeDcParamInfos( "v", "V" ); + static std::vector idc = makeDcParamInfos( "i", "A" ); - static std::vector vsin = makeSin( "v", "V" ); - static std::vector isin = makeSin( "i", "A" ); + static std::vector vsin = makeSinParamInfos( "v", "V" ); + static std::vector isin = makeSinParamInfos( "i", "A" ); - static std::vector vpulse = makePulse( "v", "V" ); - static std::vector ipulse = makePulse( "i", "A" ); + static std::vector vpulse = makePulseParamInfos( "v", "V" ); + static std::vector ipulse = makePulseParamInfos( "i", "A" ); - static std::vector vexp = makeExp( "v", "V" ); - static std::vector iexp = makeExp( "i", "A" ); + static std::vector vexp = makeExpParamInfos( "v", "V" ); + static std::vector iexp = makeExpParamInfos( "i", "A" ); - static std::vector vsfam = makeSfam( "v", "V" ); - static std::vector isfam = makeSfam( "i", "A" ); + static std::vector vsfam = makeSfamParamInfos( "v", "V" ); + static std::vector isfam = makeSfamParamInfos( "i", "A" ); - static std::vector vsffm = makeSffm( "v", "V" ); - static std::vector isffm = makeSffm( "i", "A" ); + static std::vector vsffm = makeSffmParamInfos( "v", "V" ); + static std::vector isffm = makeSffmParamInfos( "i", "A" ); - static std::vector vpwl = makePwl( "v", "Voltage", "V" ); - static std::vector ipwl = makePwl( "i", "Current", "A" ); + static std::vector vpwl = makePwlParamInfos( "v", "Voltage", "V" ); + static std::vector ipwl = makePwlParamInfos( "i", "Current", "A" ); - static std::vector vwhitenoise = makeWhiteNoise( "v", "V" ); - static std::vector iwhitenoise = makeWhiteNoise( "i", "A" ); + static std::vector vwhitenoise = makeWhiteNoiseParamInfos( "v", "V" ); + static std::vector iwhitenoise = makeWhiteNoiseParamInfos( "i", "A" ); - static std::vector vpinknoise = makePinkNoise( "v", "V" ); - static std::vector ipinknoise = makePinkNoise( "i", "A" ); + static std::vector vpinknoise = makePinkNoiseParamInfos( "v", "V" ); + static std::vector ipinknoise = makePinkNoiseParamInfos( "i", "A" ); - static std::vector vburstnoise = makeBurstNoise( "v", "V" ); - static std::vector iburstnoise = makeBurstNoise( "i", "A" ); + static std::vector vburstnoise = makeBurstNoiseParamInfos( "v", "V" ); + static std::vector iburstnoise = makeBurstNoiseParamInfos( "i", "A" ); - static std::vector vrandomuniform = makeRandomUniform( "v", "V" ); - static std::vector irandomuniform = makeRandomUniform( "i", "A" ); + static std::vector vrandomuniform = makeRandomUniformParamInfos( "v", "V" ); + static std::vector irandomuniform = makeRandomUniformParamInfos( "i", "A" ); - static std::vector vrandomnormal = makeRandomNormal( "v", "V" ); - static std::vector irandomnormal = makeRandomNormal( "i", "A" ); + static std::vector vrandomnormal = makeRandomNormalParamInfos( "v", "V" ); + static std::vector irandomnormal = makeRandomNormalParamInfos( "i", "A" ); - static std::vector vrandomexp = makeRandomExp( "v", "V" ); - static std::vector irandomexp = makeRandomExp( "i", "A" ); + static std::vector vrandomexp = makeRandomExpParamInfos( "v", "V" ); + static std::vector irandomexp = makeRandomExpParamInfos( "i", "A" ); - static std::vector vrandompoisson = makeRandomPoisson( "v", "V" ); - static std::vector irandompoisson = makeRandomPoisson( "i", "A" ); + static std::vector vrandompoisson = makeRandomPoissonParamInfos( "v", "V" ); + static std::vector irandompoisson = makeRandomPoissonParamInfos( "i", "A" ); switch( aType ) { @@ -138,19 +177,19 @@ const std::vector& SIM_MODEL_SOURCE::makeParams( TYPE aType ) } -bool SIM_MODEL_SOURCE::SetParamValue( int aParamIndex, const wxString& aValue, +bool SIM_MODEL_SOURCE::SetParamValue( unsigned aParamIndex, const wxString& aValue, SIM_VALUE_GRAMMAR::NOTATION aNotation ) { // Sources are special. All preceding parameter values must be filled. If they are not, fill // them out automatically. If a value is nulled, delete everything after it. if( aValue.IsEmpty() ) { - for( int i = aParamIndex; i < GetParamCount(); ++i ) + for( unsigned i = aParamIndex; i < GetParamCount(); ++i ) SIM_MODEL::SetParamValue( i, "", aNotation ); } else { - for( int i = 0; i < aParamIndex; ++i ) + for( unsigned i = 0; i < aParamIndex; ++i ) { if( GetParam( i ).value->ToString().IsEmpty() ) SIM_MODEL::SetParamValue( i, "0", aNotation ); @@ -161,13 +200,48 @@ bool SIM_MODEL_SOURCE::SetParamValue( int aParamIndex, const wxString& aValue, } +wxString SIM_MODEL_SOURCE::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const +{ + if( aParam.value->ToString() == "0" ) + return ""; + + return SIM_MODEL::GenerateParamValuePair( aParam, aIsFirst ); +} + + +template +void SIM_MODEL_SOURCE::inferredReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) +{ + ParsePinsField( aSymbolPinCount, PINS_FIELD ); + + if( ( InferTypeFromRef( GetFieldValue( aFields, REFERENCE_FIELD ) ) == GetType() + && ParseParamsField( GetFieldValue( aFields, VALUE_FIELD ) ) ) + || GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue ) + { + m_isInferred = true; + } +} + + +template +void SIM_MODEL_SOURCE::inferredWriteDataFields( std::vector& aFields ) const +{ + wxString value = GetFieldValue( &aFields, PARAMS_FIELD ); + + if( value.IsEmpty() ) + value = DeviceTypeInfo( GetDeviceType() ).fieldValue; + + WriteInferredDataFields( aFields, value ); +} + + std::vector SIM_MODEL_SOURCE::getPinNames() const { return { "+", "-" }; } -std::vector SIM_MODEL_SOURCE::makeDc( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeDcParamInfos( wxString aPrefix, wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -184,7 +258,7 @@ std::vector SIM_MODEL_SOURCE::makeDc( wxString aPrefix, wxString aU } -std::vector SIM_MODEL_SOURCE::makeSin( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeSinParamInfos( wxString aPrefix, wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -241,7 +315,7 @@ std::vector SIM_MODEL_SOURCE::makeSin( wxString aPrefix, wxString a } -std::vector SIM_MODEL_SOURCE::makePulse( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makePulseParamInfos( wxString aPrefix, wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -314,7 +388,7 @@ std::vector SIM_MODEL_SOURCE::makePulse( wxString aPrefix, wxString } -std::vector SIM_MODEL_SOURCE::makeExp( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeExpParamInfos( wxString aPrefix, wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -371,7 +445,7 @@ std::vector SIM_MODEL_SOURCE::makeExp( wxString aPrefix, wxString a } -std::vector SIM_MODEL_SOURCE::makeSfam( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeSfamParamInfos( wxString aPrefix, wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -419,7 +493,7 @@ std::vector SIM_MODEL_SOURCE::makeSfam( wxString aPrefix, wxString } -std::vector SIM_MODEL_SOURCE::makeSffm( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeSffmParamInfos( wxString aPrefix, wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -484,8 +558,8 @@ std::vector SIM_MODEL_SOURCE::makeSffm( wxString aPrefix, wxString } -std::vector SIM_MODEL_SOURCE::makePwl( wxString aPrefix, wxString aQuantity, - wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makePwlParamInfos( wxString aPrefix, wxString aQuantity, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -526,7 +600,8 @@ std::vector SIM_MODEL_SOURCE::makePwl( wxString aPrefix, wxString a } -std::vector SIM_MODEL_SOURCE::makeWhiteNoise( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeWhiteNoiseParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -559,7 +634,8 @@ std::vector SIM_MODEL_SOURCE::makeWhiteNoise( wxString aPrefix, wxS } -std::vector SIM_MODEL_SOURCE::makePinkNoise( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makePinkNoiseParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -600,7 +676,8 @@ std::vector SIM_MODEL_SOURCE::makePinkNoise( wxString aPrefix, wxSt } -std::vector SIM_MODEL_SOURCE::makeBurstNoise( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeBurstNoiseParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -641,7 +718,8 @@ std::vector SIM_MODEL_SOURCE::makeBurstNoise( wxString aPrefix, wxS } -std::vector SIM_MODEL_SOURCE::makeRandomUniform( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeRandomUniformParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -674,7 +752,8 @@ std::vector SIM_MODEL_SOURCE::makeRandomUniform( wxString aPrefix, } -std::vector SIM_MODEL_SOURCE::makeRandomNormal( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeRandomNormalParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -707,7 +786,8 @@ std::vector SIM_MODEL_SOURCE::makeRandomNormal( wxString aPrefix, w } -std::vector SIM_MODEL_SOURCE::makeRandomExp( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeRandomExpParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; @@ -740,7 +820,8 @@ std::vector SIM_MODEL_SOURCE::makeRandomExp( wxString aPrefix, wxSt } -std::vector SIM_MODEL_SOURCE::makeRandomPoisson( wxString aPrefix, wxString aUnit ) +std::vector SIM_MODEL_SOURCE::makeRandomPoissonParamInfos( wxString aPrefix, + wxString aUnit ) { std::vector paramInfos; PARAM::INFO paramInfo; diff --git a/eeschema/sim/sim_model_source.h b/eeschema/sim/sim_model_source.h index 24835ccbbc..cdbd99ae84 100644 --- a/eeschema/sim/sim_model_source.h +++ b/eeschema/sim/sim_model_source.h @@ -33,35 +33,53 @@ class SIM_MODEL_SOURCE : public SIM_MODEL public: SIM_MODEL_SOURCE( TYPE aType ); + void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; + void ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; + + 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& aPinNetNames ) const override; - bool SetParamValue( int aParamIndex, const wxString& aValue, + bool SetParamValue( unsigned aParamIndex, const wxString& aValue, SIM_VALUE_GRAMMAR::NOTATION aNotation ) override; bool HasAutofill() const override { return true; } +protected: + wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override; + private: + template + void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); + + template + void inferredWriteDataFields( std::vector& aFields ) const; + std::vector getPinNames() const override; - static const std::vector& makeParams( TYPE aType ); + static const std::vector& makeParamInfos( TYPE aType ); - static std::vector makeDc( wxString aPrefix, wxString aUnit ); - static std::vector makeSin( wxString aPrefix, wxString aUnit ); - static std::vector makePulse( wxString aPrefix, wxString aUnit ); - static std::vector makeExp( wxString aPrefix, wxString aUnit ); - static std::vector makeSfam( wxString aPrefix, wxString aUnit ); - static std::vector makeSffm( wxString aPrefix, wxString aUnit ); - static std::vector makePwl( wxString aPrefix, wxString aQuantity, wxString aUnit ); - static std::vector makeWhiteNoise( wxString aPrefix, wxString aUnit ); - static std::vector makePinkNoise( wxString aPrefix, wxString aUnit ); - static std::vector makeBurstNoise( wxString aPrefix, wxString aUnit ); - static std::vector makeRandomUniform( wxString aPrefix, wxString aUnit ); - static std::vector makeRandomNormal( wxString aPrefix, wxString aUnit ); - static std::vector makeRandomExp( wxString aPrefix, wxString aUnit ); - static std::vector makeRandomPoisson( wxString aPrefix, wxString aUnit ); + static std::vector makeDcParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeSinParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makePulseParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeExpParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeSfamParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeSffmParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makePwlParamInfos( wxString aPrefix, wxString aQuantity, + wxString aUnit ); + static std::vector makeWhiteNoiseParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makePinkNoiseParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeBurstNoiseParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeRandomUniformParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeRandomNormalParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeRandomExpParamInfos( wxString aPrefix, wxString aUnit ); + static std::vector makeRandomPoissonParamInfos( wxString aPrefix, wxString aUnit ); + + bool m_isInferred; }; #endif // SIM_MODEL_SOURCE_H diff --git a/eeschema/sim/sim_model_spice.cpp b/eeschema/sim/sim_model_spice.cpp index fabd7b1642..c1a3e264e6 100644 --- a/eeschema/sim/sim_model_spice.cpp +++ b/eeschema/sim/sim_model_spice.cpp @@ -25,19 +25,107 @@ #include #include #include +#include -SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType ) +SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType ) : SIM_MODEL( aType ) { + static std::vector paramInfos = makeParamInfos(); + + for( const PARAM::INFO& paramInfo : paramInfos ) + AddParam( paramInfo ); } -bool SIM_MODEL_RAWSPICE::setParamFromSpiceCode( const wxString& aParamName, - const wxString& aParamValue, - SIM_VALUE_GRAMMAR::NOTATION aNotation ) +void SIM_MODEL_SPICE::ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) { - int i = 0; + LOCALE_IO toggle; + + for( unsigned i = 0; i < aSymbolPinCount; ++i ) + AddPin( { wxString::Format( "%d", i + 1 ), i + 1 } ); + + SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields ); + readLegacyDataFields( aSymbolPinCount, aFields ); +} + + +void SIM_MODEL_SPICE::ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ) +{ + LOCALE_IO toggle; + + for( unsigned i = 0; i < aSymbolPinCount; ++i ) + AddPin( { wxString::Format( "%d", i + 1 ), i + 1 } ); + + SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields ); + readLegacyDataFields( aSymbolPinCount, aFields ); +} + + +void SIM_MODEL_SPICE::WriteDataSchFields( std::vector& aFields ) const +{ + SIM_MODEL::WriteDataSchFields( aFields ); + + // Erase the legacy fields. + SetFieldValue( aFields, LEGACY_TYPE_FIELD, "" ); + SetFieldValue( aFields, LEGACY_PINS_FIELD, "" ); + SetFieldValue( aFields, LEGACY_MODEL_FIELD, "" ); + SetFieldValue( aFields, LEGACY_ENABLED_FIELD, "" ); + SetFieldValue( aFields, LEGACY_LIB_FIELD, "" ); +} + + +void SIM_MODEL_SPICE::WriteDataLibFields( std::vector& aFields ) const +{ + SIM_MODEL::WriteDataLibFields( aFields ); +} + + +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.IsEmpty() && aRefName.StartsWith( elementType ) ) + return aRefName; + else + return elementType + aRefName; +} + + +wxString SIM_MODEL_SPICE::GenerateSpiceItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aPinNetNames ) const +{ + wxString result = ""; + result << GenerateSpiceItemName( aRefName ) << " "; + + for( unsigned i = 0; i < GetPinCount(); ++i ) + { + for( unsigned j = 0; j < aPinNetNames.size(); ++j ) + { + unsigned symbolPinNumber = j + 1; + + if( symbolPinNumber == GetPin( i ).symbolPinNumber ) + result << aPinNetNames[j] << " "; + } + } + + result << GetParam( static_cast( SPICE_PARAM::MODEL ) ).value->ToString() << "\n"; + return result; +} + + +bool SIM_MODEL_SPICE::SetParamFromSpiceCode( const wxString& aParamName, + const wxString& aParamValue, + SIM_VALUE_GRAMMAR::NOTATION aNotation ) +{ + unsigned i = 0; for(; i < GetParamCount(); ++i ) { @@ -45,7 +133,6 @@ bool SIM_MODEL_RAWSPICE::setParamFromSpiceCode( const wxString& aParamName, break; } - if( i == GetParamCount() ) { // No parameter with this name found. Create a new one. @@ -58,15 +145,92 @@ bool SIM_MODEL_RAWSPICE::setParamFromSpiceCode( const wxString& aParamName, AddParam( *m_paramInfos.back() ); } - try + return GetParam( i ).value->FromString( wxString( aParamValue ), aNotation ); +} + + +std::vector SIM_MODEL_SPICE::makeParamInfos() +{ + std::vector paramInfos; + + for( SPICE_PARAM spiceParam : SPICE_PARAM_ITERATOR() ) { - GetParam( i ).value->FromString( wxString( aParamValue ), aNotation ); - } - catch( const KI_PARAM_ERROR& e ) - { - // Shouldn't happen since it's TYPE::STRING. - return false; + PARAM::INFO paramInfo; + + switch( spiceParam ) + { + case SPICE_PARAM::TYPE: + paramInfo.name = "type"; + paramInfo.type = SIM_VALUE::TYPE::STRING; + paramInfo.unit = ""; + paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL; + paramInfo.defaultValue = ""; + paramInfo.description = "Spice element type"; + + paramInfos.push_back( paramInfo ); + break; + + case SPICE_PARAM::MODEL: + paramInfo.name = "model"; + paramInfo.type = SIM_VALUE::TYPE::STRING; + paramInfo.unit = ""; + paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL; + paramInfo.defaultValue = ""; + paramInfo.description = "Model name or value"; + + paramInfos.push_back( paramInfo ); + break; + + case SPICE_PARAM::LIB: + paramInfo.name = "lib"; + paramInfo.type = SIM_VALUE::TYPE::STRING; + paramInfo.unit = ""; + paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL; + paramInfo.defaultValue = ""; + paramInfo.description = "Library path to include"; + + paramInfos.push_back( paramInfo ); + break; + + case SPICE_PARAM::_ENUM_END: + break; + } } - return true; + return paramInfos; +} + + +template +void SIM_MODEL_SPICE::readLegacyDataFields( unsigned aSymbolPinCount, const std::vector* aFields ) +{ + // Fill in the blanks with the legacy parameters. + + if( GetParam( static_cast( SPICE_PARAM::TYPE ) ).value->ToString().IsEmpty() ) + { + SetParamValue( static_cast( SPICE_PARAM::TYPE ), + GetFieldValue( aFields, LEGACY_TYPE_FIELD ) ); + } + + if( GetFieldValue( aFields, PINS_FIELD ).IsEmpty() ) + ParsePinsField( aSymbolPinCount, GetFieldValue( aFields, LEGACY_PINS_FIELD ) ); + + if( GetParam( static_cast( SPICE_PARAM::MODEL ) ).value->ToString().IsEmpty() ) + { + SetParamValue( static_cast( SPICE_PARAM::MODEL ), + GetFieldValue( aFields, LEGACY_MODEL_FIELD ) ); + } + + // If model param is still empty, then use Value field. + if( GetParam( static_cast( SPICE_PARAM::MODEL ) ).value->ToString().IsEmpty() ) + { + SetParamValue( static_cast( SPICE_PARAM::MODEL ), + GetFieldValue( aFields, SIM_MODEL::VALUE_FIELD ) ); + } + + if( GetParam( static_cast( SPICE_PARAM::LIB ) ).value->ToString().IsEmpty() ) + { + SetParamValue( static_cast( SPICE_PARAM::LIB ), + GetFieldValue( aFields, LEGACY_LIB_FIELD ) ); + } } diff --git a/eeschema/sim/sim_model_spice.h b/eeschema/sim/sim_model_spice.h index 049ff001e9..645a43c547 100644 --- a/eeschema/sim/sim_model_spice.h +++ b/eeschema/sim/sim_model_spice.h @@ -22,25 +22,56 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef SIM_MODEL_RAWSPICE_H -#define SIM_MODEL_RAWSPICE_H +#ifndef SIM_MODEL_SPICE_H +#define SIM_MODEL_SPICE_H #include -class SIM_MODEL_RAWSPICE : public SIM_MODEL +class SIM_MODEL_SPICE : public SIM_MODEL { public: - SIM_MODEL_RAWSPICE( TYPE aType ); + DEFINE_ENUM_CLASS_WITH_ITERATOR( SPICE_PARAM, + TYPE, + MODEL, + LIB + ) + + static constexpr auto LEGACY_TYPE_FIELD = "Spice_Primitive"; + static constexpr auto LEGACY_PINS_FIELD = "Spice_Node_Sequence"; + static constexpr auto LEGACY_MODEL_FIELD = "Spice_Model"; + static constexpr auto LEGACY_ENABLED_FIELD = "Spice_Netlist_Enabled"; + static constexpr auto LEGACY_LIB_FIELD = "Spice_Lib_File"; + + + SIM_MODEL_SPICE( TYPE aType ); //bool ReadSpiceCode( const std::string& aSpiceCode ) override; + void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; + void ReadDataLibFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; -private: - bool setParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, + 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 GenerateSpiceItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aPinNetNames ) const override; + +protected: + bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override; +private: + std::vector makeParamInfos(); + + template + void readLegacyDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); + std::vector> m_paramInfos; }; -#endif // SIM_MODEL_RAWSPICE_H +#endif // SIM_MODEL_SPICE_H diff --git a/eeschema/sim/sim_model_subckt.cpp b/eeschema/sim/sim_model_subckt.cpp index b999774443..1f97c1ae22 100644 --- a/eeschema/sim/sim_model_subckt.cpp +++ b/eeschema/sim/sim_model_subckt.cpp @@ -123,7 +123,7 @@ std::vector SIM_MODEL_SUBCKT::GenerateSpiceCurrentNames( const wxStrin { std::vector currentNames; - for( int i = 0; i < GetPinCount(); ++i ) + for( unsigned i = 0; i < GetPinCount(); ++i ) currentNames.push_back( wxString::Format( "I(%s:%s)", GenerateSpiceItemName( aRefName ), GetPin( i ).name ) ); @@ -137,10 +137,10 @@ void SIM_MODEL_SUBCKT::SetBaseModel( const SIM_MODEL& aBaseModel ) SIM_MODEL::SetBaseModel( aBaseModel ); // Pins aren't constant for subcircuits, so they need to be copied from the base model. - for( int i = 0; i < GetBaseModel()->GetPinCount(); ++i ) + for( unsigned i = 0; i < GetBaseModel()->GetPinCount(); ++i ) AddPin( GetBaseModel()->GetPin( i ) ); // Same for parameters. - for( int i = 0; i < GetBaseModel()->GetParamCount(); ++i ) + for( unsigned i = 0; i < GetBaseModel()->GetParamCount(); ++i ) AddParam( GetBaseModel()->GetParam( i ).info ); } diff --git a/eeschema/sim/sim_value.cpp b/eeschema/sim/sim_value.cpp index 9a8064c861..50fecd0bb5 100644 --- a/eeschema/sim/sim_value.cpp +++ b/eeschema/sim/sim_value.cpp @@ -293,32 +293,32 @@ wxString SIM_VALUE_PARSER::ExponentToMetricSuffix( double aExponent, long& aRedu aReductionExponent = -18; return "a"; } - else if( aExponent > -15 && aExponent <= -12 ) + else if( aExponent >= -15 && aExponent < -12 ) { aReductionExponent = -15; return "f"; } - else if( aExponent > -12 && aExponent <= -9 ) + else if( aExponent >= -12 && aExponent < -9 ) { aReductionExponent = -12; return "p"; } - else if( aExponent > -9 && aExponent <= -6 ) + else if( aExponent >= -9 && aExponent < -6 ) { aReductionExponent = -9; return "n"; } - else if( aExponent > -6 && aExponent <= -3 ) + else if( aExponent >= -6 && aExponent < -3 ) { aReductionExponent = -6; return "u"; } - else if( aExponent > -3 && aExponent < 0 ) + else if( aExponent >= -3 && aExponent < 0 ) { aReductionExponent = -3; return "m"; } - else if( aExponent > 0 && aExponent < 3 ) + else if( aExponent >= 0 && aExponent < 3 ) { aReductionExponent = 0; return ""; @@ -529,7 +529,7 @@ wxString SIM_VALUE_INSTANCE::ToString( NOTATION aNotation ) const { LOCALE_IO toggle; - if( m_value.has_value() ) + if( m_value ) return wxString::Format( "%d", *m_value ); return ""; @@ -541,12 +541,12 @@ wxString SIM_VALUE_INSTANCE::ToString( NOTATION aNotation ) const { LOCALE_IO toggle; - if( m_value.has_value() ) + if( m_value ) { long value = *m_value; long exponent = 0; - while( value % 1000 == 0 ) + while( value != 0 && value % 1000 == 0 ) { exponent += 3; value /= 1000; @@ -567,7 +567,7 @@ wxString SIM_VALUE_INSTANCE::ToString( NOTATION aNotation ) const { LOCALE_IO toggle; - if( m_value.has_value() ) + if( m_value ) { double exponent = std::log10( *m_value ); long reductionExponent = 0; @@ -588,7 +588,7 @@ wxString SIM_VALUE_INSTANCE>::ToString( NOTATION aNotation { LOCALE_IO toggle; - if( m_value.has_value() ) + if( m_value ) return wxString::Format( "%g+%gi", m_value->real(), m_value->imag() ); return ""; @@ -600,7 +600,7 @@ wxString SIM_VALUE_INSTANCE::ToString( NOTATION aNotation ) const { LOCALE_IO toggle; - if( m_value.has_value() ) + if( m_value ) return *m_value; return ""; // Empty string is completely equivalent to null string. @@ -610,7 +610,7 @@ wxString SIM_VALUE_INSTANCE::ToString( NOTATION aNotation ) const template wxString SIM_VALUE_INSTANCE::ToSimpleString() const { - if( m_value.has_value() ) + if( m_value ) { wxString result = ""; result << *m_value; diff --git a/eeschema/sim/sim_value.h b/eeschema/sim/sim_value.h index f2b634d82c..86d60c8b2c 100644 --- a/eeschema/sim/sim_value.h +++ b/eeschema/sim/sim_value.h @@ -154,10 +154,10 @@ namespace SIM_VALUE_GRAMMAR TAO_PEGTL_ISTRING( "p" ), TAO_PEGTL_ISTRING( "n" ), TAO_PEGTL_ISTRING( "u" ), + TAO_PEGTL_ISTRING( "Meg" ), // "Meg" must be before "m". TAO_PEGTL_ISTRING( "m" ), //TAO_PEGTL_ISTRING( "mil" ), TAO_PEGTL_ISTRING( "k" ), - TAO_PEGTL_ISTRING( "Meg" ), TAO_PEGTL_ISTRING( "G" ), TAO_PEGTL_ISTRING( "T" )> {}; @@ -165,7 +165,7 @@ namespace SIM_VALUE_GRAMMAR template struct number : seq, opt, - opt>> {}; + sor, not_at>> {}; template struct numberGrammar : must>, eof> {}; diff --git a/eeschema/sim/spice_grammar.h b/eeschema/sim/spice_grammar.h index 3ec9fbc5dd..23d188bbce 100644 --- a/eeschema/sim/spice_grammar.h +++ b/eeschema/sim/spice_grammar.h @@ -76,7 +76,7 @@ namespace SPICE_GRAMMAR /*seq>>> {};*/ - struct dotModelType : sor {}; + TAO_PEGTL_ISTRING( "VDMOS" )> {};*/ + struct dotModelType : plus {}; struct dotModel : seq, TAO_PEGTL_ISTRING( ".model" ), sep, diff --git a/qa/data/eeschema/spice_netlists/opamp/opamp.kicad_sch b/qa/data/eeschema/spice_netlists/opamp/opamp.kicad_sch index 009a06a59d..b3583b7491 100644 --- a/qa/data/eeschema/spice_netlists/opamp/opamp.kicad_sch +++ b/qa/data/eeschema/spice_netlists/opamp/opamp.kicad_sch @@ -315,7 +315,7 @@ (uuid 55368b74-95a7-4cf2-8f86-415db816907d) ) - (text ".tran 10u 10m" (at 138.43 86.36 0) + (text ".tran 10u 10m" (at 146.05 123.19 0) (effects (font (size 1.27 1.27)) (justify left bottom)) (uuid be48cb8e-7c9f-4216-838e-ee151aaeb3f9) ) @@ -341,10 +341,10 @@ (symbol (lib_id "Simulation_SPICE:VSIN") (at 142.24 96.52 0) (unit 1) (in_bom yes) (on_board yes) (uuid 10f44001-5f65-44eb-a535-b7b3c67d5b83) - (property "Reference" "V1" (id 0) (at 146.05 94.615 0) + (property "Reference" "VSIN1" (id 0) (at 121.92 95.25 0) (effects (font (size 1.27 1.27)) (justify left)) ) - (property "Value" "VSIN" (id 1) (at 146.05 97.155 0) + (property "Value" "ampl=100m f=1k" (id 1) (at 121.92 97.79 0) (effects (font (size 1.27 1.27)) (justify left)) ) (property "Footprint" "" (id 2) (at 142.24 96.52 0) @@ -353,18 +353,6 @@ (property "Datasheet" "~" (id 3) (at 142.24 96.52 0) (effects (font (size 1.27 1.27)) hide) ) - (property "Model_Device" "V" (id 4) (at 142.24 96.52 0) - (effects (font (size 1.27 1.27)) hide) - ) - (property "Model_Type" "SIN" (id 5) (at 142.24 96.52 0) - (effects (font (size 1.27 1.27)) hide) - ) - (property "Model_Pins" "1 2" (id 6) (at 142.24 96.52 0) - (effects (font (size 1.27 1.27)) hide) - ) - (property "Model_Params" "dc=0 ampl=100m f=1k" (id 7) (at 129.54 92.71 0) - (effects (font (size 1.27 1.27))) - ) (pin "1" (uuid 27dbfa5d-bb20-468f-9a81-7737a5e908fc)) (pin "2" (uuid 63677ebb-93e3-49bb-8bf1-14fce6c8137d)) ) @@ -375,7 +363,7 @@ (property "Reference" "R2" (id 0) (at 156.21 116.205 90) (effects (font (size 1.27 1.27))) ) - (property "Value" "10K" (id 1) (at 156.21 118.745 90) + (property "Value" "10k" (id 1) (at 156.21 118.745 90) (effects (font (size 1.27 1.27))) ) (property "Footprint" "" (id 2) (at 156.21 115.443 90) @@ -544,7 +532,7 @@ (property "Reference" "R1" (id 0) (at 148.59 116.205 90) (effects (font (size 1.27 1.27))) ) - (property "Value" "10K" (id 1) (at 148.59 118.745 90) + (property "Value" "10k" (id 1) (at 148.59 118.745 90) (effects (font (size 1.27 1.27))) ) (property "Footprint" "" (id 2) (at 148.59 115.443 90) @@ -575,22 +563,22 @@ (reference "#PWR04") (unit 1) (value "GND") (footprint "") ) (path "/fbe00ebb-3cab-46ea-988c-9e8169e9708f" - (reference "R1") (unit 1) (value "10K") (footprint "") + (reference "R1") (unit 1) (value "10k") (footprint "") ) (path "/2a5b0448-42a8-4fa4-9a14-267dc34f9ff7" - (reference "R2") (unit 1) (value "10K") (footprint "") + (reference "R2") (unit 1) (value "10k") (footprint "") ) (path "/3dd58d42-1028-4fbc-adf4-32d03de981a6" (reference "U1") (unit 1) (value "OPAMP") (footprint "") ) - (path "/10f44001-5f65-44eb-a535-b7b3c67d5b83" - (reference "V1") (unit 1) (value "VSIN") (footprint "") - ) (path "/383ea298-1cb3-473e-8fce-19d3c7ac3912" (reference "V2") (unit 1) (value "VDC") (footprint "") ) (path "/d2018f30-5def-453e-85fe-dac327cfbe9b" (reference "V3") (unit 1) (value "VDC") (footprint "") ) + (path "/10f44001-5f65-44eb-a535-b7b3c67d5b83" + (reference "VSIN1") (unit 1) (value "ampl=100m f=1k") (footprint "") + ) ) ) diff --git a/qa/data/eeschema/spice_netlists/passives/passives.kicad_pcb b/qa/data/eeschema/spice_netlists/passives/passives.kicad_pcb new file mode 100644 index 0000000000..ee9b72bbf8 --- /dev/null +++ b/qa/data/eeschema/spice_netlists/passives/passives.kicad_pcb @@ -0,0 +1,2 @@ +(kicad_pcb (version 20220308) (generator pcbnew) +) \ No newline at end of file diff --git a/qa/data/eeschema/spice_netlists/passives/passives.kicad_pro b/qa/data/eeschema/spice_netlists/passives/passives.kicad_pro new file mode 100644 index 0000000000..ec85213554 --- /dev/null +++ b/qa/data/eeschema/spice_netlists/passives/passives.kicad_pro @@ -0,0 +1,331 @@ +{ + "board": { + "design_settings": { + "defaults": { + "board_outline_line_width": 0.1, + "copper_line_width": 0.2, + "copper_text_size_h": 1.5, + "copper_text_size_v": 1.5, + "copper_text_thickness": 0.3, + "other_line_width": 0.15, + "silk_line_width": 0.15, + "silk_text_size_h": 1.0, + "silk_text_size_v": 1.0, + "silk_text_thickness": 0.15 + }, + "diff_pair_dimensions": [], + "drc_exclusions": [], + "rules": { + "min_copper_edge_clearance": 0.0, + "solder_mask_clearance": 0.0, + "solder_mask_min_width": 0.0 + }, + "track_widths": [], + "via_dimensions": [] + }, + "layer_presets": [], + "viewports": [] + }, + "boards": [], + "cvpcb": { + "equivalence_files": [] + }, + "erc": { + "erc_exclusions": [], + "meta": { + "version": 0 + }, + "pin_map": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 2, + 0, + 1, + 0, + 0, + 1, + 0, + 2, + 2, + 2, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 2 + ], + [ + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 2, + 1, + 1, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2 + ], + [ + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 2 + ], + [ + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2 + ], + [ + 0, + 2, + 1, + 2, + 0, + 0, + 1, + 0, + 2, + 2, + 2, + 2 + ], + [ + 0, + 2, + 0, + 1, + 0, + 0, + 1, + 0, + 2, + 0, + 0, + 2 + ], + [ + 0, + 2, + 1, + 1, + 0, + 0, + 1, + 0, + 2, + 0, + 0, + 2 + ], + [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2 + ] + ], + "rule_severities": { + "bus_definition_conflict": "error", + "bus_entry_needed": "error", + "bus_label_syntax": "error", + "bus_to_bus_conflict": "error", + "bus_to_net_conflict": "error", + "different_unit_footprint": "error", + "different_unit_net": "error", + "duplicate_reference": "error", + "duplicate_sheet_names": "error", + "extra_units": "error", + "global_label_dangling": "warning", + "hier_label_mismatch": "error", + "label_dangling": "error", + "lib_symbol_issues": "warning", + "multiple_net_names": "warning", + "net_not_bus_member": "warning", + "no_connect_connected": "warning", + "no_connect_dangling": "warning", + "pin_not_connected": "error", + "pin_not_driven": "error", + "pin_to_pin": "warning", + "power_pin_not_driven": "error", + "similar_labels": "warning", + "unannotated": "error", + "unit_value_mismatch": "error", + "unresolved_variable": "error", + "wire_dangling": "error" + } + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "passives.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12.0, + "clearance": 0.2, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.25, + "via_diameter": 0.8, + "via_drill": 0.4, + "wire_width": 6.0 + } + ], + "meta": { + "version": 2 + }, + "net_colors": null + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "specctra_dsn": "", + "step": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "annotate_start_num": 0, + "drawing": { + "dashed_lines_dash_length_ratio": 12.0, + "dashed_lines_gap_length_ratio": 3.0, + "default_line_thickness": 6.0, + "default_text_size": 50.0, + "field_names": [], + "intersheets_ref_own_page": false, + "intersheets_ref_prefix": "", + "intersheets_ref_short": false, + "intersheets_ref_show": false, + "intersheets_ref_suffix": "", + "junction_size_choice": 3, + "label_size_ratio": 0.375, + "pin_symbol_size": 25.0, + "text_offset_ratio": 0.15 + }, + "legacy_lib_dir": "", + "legacy_lib_list": [], + "meta": { + "version": 1 + }, + "net_format_name": "", + "ngspice": { + "fix_include_paths": true, + "fix_passive_vals": false, + "meta": { + "version": 0 + }, + "model_mode": 0, + "workbook_filename": "" + }, + "page_layout_descr_file": "", + "plot_directory": "", + "spice_adjust_passive_values": false, + "spice_external_command": "spice \"%I\"", + "spice_save_all_currents": false, + "spice_save_all_voltages": false, + "subpart_first_id": 65, + "subpart_id_separator": 0 + }, + "sheets": [ + [ + "24a3b022-7ece-4686-93db-0efadfbf9409", + "" + ] + ], + "text_variables": {} +} diff --git a/qa/data/eeschema/spice_netlists/passives/passives.kicad_sch b/qa/data/eeschema/spice_netlists/passives/passives.kicad_sch new file mode 100644 index 0000000000..4c4ac514e4 --- /dev/null +++ b/qa/data/eeschema/spice_netlists/passives/passives.kicad_sch @@ -0,0 +1,681 @@ +(kicad_sch (version 20220331) (generator eeschema) + + (uuid 24a3b022-7ece-4686-93db-0efadfbf9409) + + (paper "A4") + + (lib_symbols + (symbol "Device:C" (pin_numbers hide) (pin_names (offset 0.254)) (in_bom yes) (on_board yes) + (property "Reference" "C" (id 0) (at 0.635 2.54 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "C" (id 1) (at 0.635 -2.54 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 0.9652 -3.81 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "cap capacitor" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Unpolarized capacitor" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_fp_filters" "C_*" (id 6) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "C_0_1" + (polyline + (pts + (xy -2.032 -0.762) + (xy 2.032 -0.762) + ) + (stroke (width 0.508) (type default)) + (fill (type none)) + ) + (polyline + (pts + (xy -2.032 0.762) + (xy 2.032 0.762) + ) + (stroke (width 0.508) (type default)) + (fill (type none)) + ) + ) + (symbol "C_1_1" + (pin passive line (at 0 3.81 270) (length 2.794) + (name "~" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 0 -3.81 90) (length 2.794) + (name "~" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "Device:L" (pin_numbers hide) (pin_names (offset 1.016) hide) (in_bom yes) (on_board yes) + (property "Reference" "L" (id 0) (at -1.27 0 90) + (effects (font (size 1.27 1.27))) + ) + (property "Value" "L" (id 1) (at 1.905 0 90) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "inductor choke coil reactor magnetic" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Inductor" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_fp_filters" "Choke_* *Coil* Inductor_* L_*" (id 6) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "L_0_1" + (arc (start 0 -2.54) (mid 0.635 -1.905) (end 0 -1.27) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (arc (start 0 -1.27) (mid 0.635 -0.635) (end 0 0) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (arc (start 0 0) (mid 0.635 0.635) (end 0 1.27) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (arc (start 0 1.27) (mid 0.635 1.905) (end 0 2.54) + (stroke (width 0) (type default)) + (fill (type none)) + ) + ) + (symbol "L_1_1" + (pin passive line (at 0 3.81 270) (length 1.27) + (name "1" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 0 -3.81 90) (length 1.27) + (name "2" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "Device:R" (pin_numbers hide) (pin_names (offset 0)) (in_bom yes) (on_board yes) + (property "Reference" "R" (id 0) (at 2.032 0 90) + (effects (font (size 1.27 1.27))) + ) + (property "Value" "R" (id 1) (at 0 0 90) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at -1.778 0 90) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "R res resistor" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Resistor" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_fp_filters" "R_*" (id 6) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "R_0_1" + (rectangle (start -1.016 -2.54) (end 1.016 2.54) + (stroke (width 0.254) (type default)) + (fill (type none)) + ) + ) + (symbol "R_1_1" + (pin passive line (at 0 3.81 270) (length 1.27) + (name "~" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 0 -3.81 90) (length 1.27) + (name "~" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "Simulation_SPICE:VDC" (pin_numbers hide) (pin_names (offset 0.0254)) (in_bom yes) (on_board yes) + (property "Reference" "V" (id 0) (at 2.54 2.54 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "VDC" (id 1) (at 2.54 0 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Spice_Netlist_Enabled" "Y" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) (justify left) hide) + ) + (property "Spice_Primitive" "V" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) (justify left) hide) + ) + (property "Spice_Model" "dc(1)" (id 6) (at 2.54 -2.54 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "ki_keywords" "simulation" (id 7) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Voltage source, DC" (id 8) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "VDC_0_0" + (polyline + (pts + (xy -1.27 0.254) + (xy 1.27 0.254) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (polyline + (pts + (xy -0.762 -0.254) + (xy -1.27 -0.254) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (polyline + (pts + (xy 0.254 -0.254) + (xy -0.254 -0.254) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (polyline + (pts + (xy 1.27 -0.254) + (xy 0.762 -0.254) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (text "+" (at 0 1.905 0) + (effects (font (size 1.27 1.27))) + ) + ) + (symbol "VDC_0_1" + (circle (center 0 0) (radius 2.54) + (stroke (width 0.254) (type default)) + (fill (type background)) + ) + ) + (symbol "VDC_1_1" + (pin passive line (at 0 5.08 270) (length 2.54) + (name "~" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 0 -5.08 90) (length 2.54) + (name "~" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "power:GND" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes) + (property "Reference" "#PWR" (id 0) (at 0 -6.35 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 0 -3.81 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "power-flag" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Power symbol creates a global label with name \"GND\" , ground" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "GND_0_1" + (polyline + (pts + (xy 0 0) + (xy 0 -1.27) + (xy 1.27 -1.27) + (xy 0 -2.54) + (xy -1.27 -1.27) + (xy 0 -1.27) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + ) + (symbol "GND_1_1" + (pin power_in line (at 0 0 270) (length 0) hide + (name "GND" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "power:VCC" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes) + (property "Reference" "#PWR" (id 0) (at 0 -3.81 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 0 3.81 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "power-flag" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Power symbol creates a global label with name \"VCC\"" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "VCC_0_1" + (polyline + (pts + (xy -0.762 1.27) + (xy 0 2.54) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 0) + (xy 0 2.54) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 2.54) + (xy 0.762 1.27) + ) + (stroke (width 0) (type default)) + (fill (type none)) + ) + ) + (symbol "VCC_1_1" + (pin power_in line (at 0 0 90) (length 0) hide + (name "VCC" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + ) + ) + ) + + (junction (at 190.5 114.2622) (diameter 0) (color 0 0 0 0) + (uuid eafda027-8fd2-40c0-b082-f15f04050481) + ) + + (wire (pts (xy 190.5 101.6) (xy 190.5 104.14)) + (stroke (width 0) (type default)) + (uuid 03e5d1ef-95c5-418e-822d-d942eb7eea5f) + ) + (wire (pts (xy 165.1 101.6) (xy 165.1 104.14)) + (stroke (width 0) (type default)) + (uuid 215ca15f-8dc1-4558-b14d-ce81bdd98add) + ) + (wire (pts (xy 190.5 114.2622) (xy 190.5 114.3)) + (stroke (width 0) (type default)) + (uuid 35f870a7-448a-4ca6-9dc9-3095aaefc3f9) + ) + (wire (pts (xy 165.1 111.76) (xy 165.1 114.3)) + (stroke (width 0) (type default)) + (uuid 8c444764-4ee8-4e6a-b678-fea30fbd1bdb) + ) + (wire (pts (xy 139.7 111.76) (xy 139.7 114.3)) + (stroke (width 0) (type default)) + (uuid a5287d05-b271-47b7-b485-2abae8ee6bda) + ) + (wire (pts (xy 139.7 101.6) (xy 139.7 104.14)) + (stroke (width 0) (type default)) + (uuid af29e35f-ad8e-42ad-92d8-dab3c77b10f7) + ) + (wire (pts (xy 114.3 101.6) (xy 114.3 102.87)) + (stroke (width 0) (type default)) + (uuid c8381c0e-870a-4b60-a370-665e41cc0a82) + ) + (wire (pts (xy 190.5 111.76) (xy 190.5 114.2622)) + (stroke (width 0) (type default)) + (uuid c96a0874-8a88-41d8-8fc9-4f44b9a77308) + ) + (wire (pts (xy 114.3 113.03) (xy 114.3 114.3)) + (stroke (width 0) (type default)) + (uuid e4efd56a-f328-4d4d-b131-d2bd4285571c) + ) + + (text ".dc TEMP -40 125 1" (at 114.3 127 0) + (effects (font (size 1.27 1.27)) (justify left bottom)) + (uuid 7375d298-3734-4861-a3c5-951d900d6e42) + ) + + (symbol (lib_id "power:VCC") (at 139.7 101.6 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 0b5a77ca-f3ff-42b7-8572-0eefa9011bf1) + (property "Reference" "#PWR?" (id 0) (at 139.7 105.41 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 139.7 97.79 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 139.7 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 139.7 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 80684c7b-5b8f-4fa5-a22a-6c3e25ecf03a)) + ) + + (symbol (lib_id "power:VCC") (at 190.5 101.6 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 2f62470a-49dd-4c2d-89e9-a2acc60c442d) + (property "Reference" "#PWR?" (id 0) (at 190.5 105.41 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 190.5 97.79 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 190.5 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 190.5 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid d3b8058c-41bf-4fda-9fb7-d5dd8c40209d)) + ) + + (symbol (lib_id "power:GND") (at 165.1 114.3 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 438ece8c-3eb3-4d7e-9271-8a8e8aeb6d3c) + (property "Reference" "#PWR?" (id 0) (at 165.1 120.65 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 165.1 119.38 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 165.1 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 165.1 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid d4f9c990-709a-4cab-83e6-f03cac3e330c)) + ) + + (symbol (lib_id "power:VCC") (at 165.1 101.6 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 613737e0-8030-4980-b87e-8290b8a61eaf) + (property "Reference" "#PWR?" (id 0) (at 165.1 105.41 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 165.1 97.79 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 165.1 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 165.1 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 4e31b1ca-d4bc-4891-b37e-bc167f16d091)) + ) + + (symbol (lib_id "Device:C") (at 165.1 107.95 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 6566e118-05df-4951-a19e-df5ca72becf1) + (property "Reference" "C1" (id 0) (at 168.91 107.315 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "100u" (id 1) (at 168.91 109.855 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 166.0652 111.76 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 165.1 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Name" "AVX_12066D107MAT4A" (id 4) (at 165.1 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Library" "passives.lib" (id 5) (at 165.1 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Device" "C" (id 6) (at 165.1 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Type" "ADV" (id 7) (at 165.1 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid b036b9d3-38c0-48ea-9a7e-5c57025637b1)) + (pin "2" (uuid 35151b75-27a9-4e4d-b0b5-cdabe4516193)) + ) + + (symbol (lib_id "Device:L") (at 190.5 107.95 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 65be26d9-e694-445c-9a01-797abd973f29) + (property "Reference" "L1" (id 0) (at 191.77 107.315 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "220n" (id 1) (at 191.77 109.855 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 190.5 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 190.5 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Name" "AVX_0603WL221GT" (id 4) (at 190.5 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Library" "passives.lib" (id 5) (at 190.5 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Device" "L" (id 6) (at 190.5 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Type" "ADV" (id 7) (at 190.5 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 31abb371-b97b-4c10-a4b3-748d55802214)) + (pin "2" (uuid c9d49533-c142-4cb7-8d54-6a6d51b458e7)) + ) + + (symbol (lib_id "Device:R") (at 139.7 107.95 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 698024ab-bd78-4be5-8cb1-c09eef71c67f) + (property "Reference" "R1" (id 0) (at 142.24 107.315 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "10M" (id 1) (at 142.24 109.855 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 137.922 107.95 90) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 139.7 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Name" "VISHAY_CRCW060310M0FKTABC" (id 4) (at 139.7 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Library" "passives.lib" (id 5) (at 139.7 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Device" "R" (id 6) (at 139.7 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Type" "ADV" (id 7) (at 139.7 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 9258bd9f-6e64-48cb-b10a-9f0ab959f571)) + (pin "2" (uuid f024f933-67b5-408d-9af7-d6ece6042782)) + ) + + (symbol (lib_id "Simulation_SPICE:VDC") (at 114.3 107.95 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid 83608f1c-11c0-46f8-ae54-fcb488541f6a) + (property "Reference" "VDC" (id 0) (at 118.11 106.045 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "1" (id 1) (at 118.11 108.585 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 114.3 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 114.3 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Device" "V" (id 7) (at 114.3 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Pins" "1 2" (id 8) (at 114.3 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Params" "dc=1" (id 9) (at 114.3 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Model_Type" "DC" (id 10) (at 114.3 107.95 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid de407df0-899c-4dfc-8493-f9d50583d17a)) + (pin "2" (uuid 77371cba-8f4b-45a2-91a6-f825ae3f9546)) + ) + + (symbol (lib_id "power:GND") (at 190.5 114.2622 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid aa1c725b-e908-4ffe-a8e1-dbe74874ec0b) + (property "Reference" "#PWR?" (id 0) (at 190.5 120.6122 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 190.5 119.3422 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 190.5 114.2622 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 190.5 114.2622 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 08083956-7f80-48fc-a073-d7e31be1dea5)) + ) + + (symbol (lib_id "power:VCC") (at 114.3 101.6 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid b60fd0ca-97bd-4e20-9a27-3046f059d2b9) + (property "Reference" "#PWR?" (id 0) (at 114.3 105.41 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 114.3 97.79 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 114.3 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 114.3 101.6 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 03c6ace1-caf1-4775-b684-3e857b918919)) + ) + + (symbol (lib_id "power:GND") (at 114.3 114.3 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid cae1a2a0-561b-4729-802f-81c375ac4c1e) + (property "Reference" "#PWR?" (id 0) (at 114.3 120.65 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 114.3 119.38 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 114.3 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 114.3 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid b4bef1f0-ad5b-4c59-87c6-a3d88d776adf)) + ) + + (symbol (lib_id "power:GND") (at 139.7 114.3 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid d829b2e0-05c9-40a0-815e-35a8d1f6cecd) + (property "Reference" "#PWR?" (id 0) (at 139.7 120.65 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 139.7 119.38 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 139.7 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 139.7 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 924cf866-e3b9-4af1-895c-792ddd27e24d)) + ) + + (sheet_instances + (path "/" (page "1")) + ) + + (symbol_instances + (path "/0b5a77ca-f3ff-42b7-8572-0eefa9011bf1" + (reference "#PWR?") (unit 1) (value "VCC") (footprint "") + ) + (path "/2f62470a-49dd-4c2d-89e9-a2acc60c442d" + (reference "#PWR?") (unit 1) (value "VCC") (footprint "") + ) + (path "/438ece8c-3eb3-4d7e-9271-8a8e8aeb6d3c" + (reference "#PWR?") (unit 1) (value "GND") (footprint "") + ) + (path "/613737e0-8030-4980-b87e-8290b8a61eaf" + (reference "#PWR?") (unit 1) (value "VCC") (footprint "") + ) + (path "/aa1c725b-e908-4ffe-a8e1-dbe74874ec0b" + (reference "#PWR?") (unit 1) (value "GND") (footprint "") + ) + (path "/b60fd0ca-97bd-4e20-9a27-3046f059d2b9" + (reference "#PWR?") (unit 1) (value "VCC") (footprint "") + ) + (path "/cae1a2a0-561b-4729-802f-81c375ac4c1e" + (reference "#PWR?") (unit 1) (value "GND") (footprint "") + ) + (path "/d829b2e0-05c9-40a0-815e-35a8d1f6cecd" + (reference "#PWR?") (unit 1) (value "GND") (footprint "") + ) + (path "/6566e118-05df-4951-a19e-df5ca72becf1" + (reference "C1") (unit 1) (value "100u") (footprint "") + ) + (path "/65be26d9-e694-445c-9a01-797abd973f29" + (reference "L1") (unit 1) (value "220n") (footprint "") + ) + (path "/698024ab-bd78-4be5-8cb1-c09eef71c67f" + (reference "R1") (unit 1) (value "10M") (footprint "") + ) + (path "/83608f1c-11c0-46f8-ae54-fcb488541f6a" + (reference "VDC") (unit 1) (value "1") (footprint "") + ) + ) +) diff --git a/qa/data/eeschema/spice_netlists/passives/passives.lib b/qa/data/eeschema/spice_netlists/passives/passives.lib new file mode 100644 index 0000000000..14d958d6b2 --- /dev/null +++ b/qa/data/eeschema/spice_netlists/passives/passives.lib @@ -0,0 +1,11 @@ +* +* Resistors +.model PT100 R(R=100 Tnom=0 tc1=3.85m noisy=0) +.model VISHAY_CRCW060310M0FKTABC R(R=10Meg Tnom=20 tc1=100u) ; bv_max=75 - idk if we should include that + +* Capacitors +.model AVX_12066D107MAT4A C(C=100u Tnom=15 tc1=21.4u) + +* Inductors +.model AVX_0603WL221GT L(ind=220n Tnom=20 tc1=125u) + diff --git a/qa/data/eeschema/spice_netlists/rectifier/diode.lib b/qa/data/eeschema/spice_netlists/rectifier/diode.lib index b35513c33b..91056f0656 100644 --- a/qa/data/eeschema/spice_netlists/rectifier/diode.lib +++ b/qa/data/eeschema/spice_netlists/rectifier/diode.lib @@ -4,4 +4,4 @@ .MODEL DIODE1 D (IS=100E-15 RS=10 CJO=1P TT=12N BV=120 IBV=100E-15) * Diode 2 -.MODEL DIODE2 D (IS=100E-15 RS=8 CJO=1.5P TT=11N BV=100 IBV=100E-15) +.MODEL DIODE2 D (JS=100E-15 RS=8 CJ0=1.5P TT=11N BV=100 IBV=100E-15) diff --git a/qa/data/eeschema/spice_netlists/rectifier/rectifier.kicad_sch b/qa/data/eeschema/spice_netlists/rectifier/rectifier.kicad_sch index fbf5af7a48..b3786e07eb 100644 --- a/qa/data/eeschema/spice_netlists/rectifier/rectifier.kicad_sch +++ b/qa/data/eeschema/spice_netlists/rectifier/rectifier.kicad_sch @@ -320,12 +320,12 @@ ) (symbol (lib_id "Simulation_SPICE:VSIN") (at 134.62 101.6 0) (unit 1) - (in_bom yes) (on_board yes) (fields_autoplaced) + (in_bom yes) (on_board yes) (uuid 2f4ce84c-7613-4135-9bc6-7662b55052cf) - (property "Reference" "V1" (id 0) (at 138.43 99.695 0) + (property "Reference" "VSIN" (id 0) (at 118.11 99.06 0) (effects (font (size 1.27 1.27)) (justify left)) ) - (property "Value" "VSIN" (id 1) (at 138.43 102.235 0) + (property "Value" "" (id 1) (at 118.11 101.6 0) (effects (font (size 1.27 1.27)) (justify left)) ) (property "Footprint" "" (id 2) (at 134.62 101.6 0) @@ -334,18 +334,6 @@ (property "Datasheet" "~" (id 3) (at 134.62 101.6 0) (effects (font (size 1.27 1.27)) hide) ) - (property "Model_Device" "V" (id 4) (at 134.62 101.6 0) - (effects (font (size 1.27 1.27)) hide) - ) - (property "Model_Type" "SIN" (id 5) (at 134.62 101.6 0) - (effects (font (size 1.27 1.27)) hide) - ) - (property "Model_Pins" "1 2" (id 6) (at 134.62 101.6 0) - (effects (font (size 1.27 1.27)) hide) - ) - (property "Model_Params" "dc=0 ampl=5 f=10k" (id 7) (at 134.62 101.6 0) - (effects (font (size 1.27 1.27)) hide) - ) (pin "1" (uuid a29d8f63-65fa-4d69-b0d4-cfa5c00fc5ab)) (pin "2" (uuid 8bfe05fb-6889-4435-80ba-ab2128b151d8)) ) @@ -406,7 +394,7 @@ (property "Reference" "R1" (id 0) (at 167.64 99.695 0) (effects (font (size 1.27 1.27)) (justify left)) ) - (property "Value" "100K" (id 1) (at 167.64 102.235 0) + (property "Value" "" (id 1) (at 167.64 102.235 0) (effects (font (size 1.27 1.27)) (justify left)) ) (property "Footprint" "" (id 2) (at 163.322 100.33 90) @@ -458,10 +446,10 @@ (reference "D1") (unit 1) (value "D") (footprint "") ) (path "/7ae05049-58f1-4d14-9a95-35ba665c7986" - (reference "R1") (unit 1) (value "100K") (footprint "") + (reference "R1") (unit 1) (value "10K") (footprint "") ) (path "/2f4ce84c-7613-4135-9bc6-7662b55052cf" - (reference "V1") (unit 1) (value "VSIN") (footprint "") + (reference "VSIN") (unit 1) (value "ampl=5 f=1k") (footprint "") ) ) ) diff --git a/qa/unittests/eeschema/sim/test_ngspice.cpp b/qa/unittests/eeschema/sim/test_ngspice.cpp index 1c839231bc..473fbff593 100644 --- a/qa/unittests/eeschema/sim/test_ngspice.cpp +++ b/qa/unittests/eeschema/sim/test_ngspice.cpp @@ -34,8 +34,8 @@ BOOST_AUTO_TEST_CASE( Models ) for( NGSPICE::MODEL_TYPE type : NGSPICE::MODEL_TYPE_ITERATOR() ) { - unsigned int modelParamCount = NGSPICE::ModelInfo( type ).modelParams.size(); - unsigned int instanceParamCount = NGSPICE::ModelInfo( type ).instanceParams.size(); + unsigned modelParamCount = NGSPICE::ModelInfo( type ).modelParams.size(); + unsigned instanceParamCount = NGSPICE::ModelInfo( type ).instanceParams.size(); switch( type ) { @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE( Models ) case NGSPICE::MODEL_TYPE::_ENUM_END: break; - case NGSPICE::MODEL_TYPE::RESISTOR: + /*case NGSPICE::MODEL_TYPE::RESISTOR: BOOST_CHECK_EQUAL( modelParamCount, 22 ); BOOST_CHECK_EQUAL( instanceParamCount, 25 ); break; @@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE( Models ) case NGSPICE::MODEL_TYPE::INDUCTOR: BOOST_CHECK_EQUAL( modelParamCount, 9 ); BOOST_CHECK_EQUAL( instanceParamCount, 20 ); - break; + break;*/ case NGSPICE::MODEL_TYPE::LTRA: BOOST_CHECK_EQUAL( modelParamCount, 18 ); diff --git a/qa/unittests/eeschema/test_netlist_exporter_spice.cpp b/qa/unittests/eeschema/test_netlist_exporter_spice.cpp index 015edf88eb..de5df9e17b 100644 --- a/qa/unittests/eeschema/test_netlist_exporter_spice.cpp +++ b/qa/unittests/eeschema/test_netlist_exporter_spice.cpp @@ -109,4 +109,10 @@ BOOST_AUTO_TEST_CASE( NpnCeAmp ) } +BOOST_AUTO_TEST_CASE( Passives ) +{ + TestNetlist( "passives" ); +} + + BOOST_AUTO_TEST_SUITE_END()