Migrate more V6 SPICE syntax to V7.
Also fixes various bugs if symbols contained non-indexed pin numbers. We really need to know the actual pin names when creating models, rather than just assuming 1, 2... etc. Fixes https://gitlab.com/kicad/code/kicad/issues/13183
This commit is contained in:
parent
1047e7143a
commit
6b70c679cf
|
@ -240,14 +240,22 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
||||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
|
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
|
||||||
|
|
||||||
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
||||||
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
||||||
|
{
|
||||||
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
||||||
|
} );
|
||||||
|
|
||||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
|
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
|
||||||
m_builtinModelsMgr.CreateModel( m_fields, m_symbol.GetFullPinCount() );
|
m_builtinModelsMgr.CreateModel( m_fields, sourcePins );
|
||||||
else
|
else
|
||||||
m_builtinModelsMgr.CreateModel( type, m_symbol.GetFullPinCount() );
|
m_builtinModelsMgr.CreateModel( type, sourcePins );
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& e )
|
catch( const IO_ERROR& e )
|
||||||
{
|
{
|
||||||
|
@ -656,6 +664,14 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
|
||||||
|
|
||||||
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
||||||
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
||||||
|
{
|
||||||
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
||||||
|
} );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
||||||
|
@ -663,9 +679,9 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
||||||
for( auto& [baseModelName, baseModel] : library()->GetModels() )
|
for( auto& [baseModelName, baseModel] : library()->GetModels() )
|
||||||
{
|
{
|
||||||
if( baseModelName == modelName )
|
if( baseModelName == modelName )
|
||||||
m_libraryModelsMgr.CreateModel( baseModel, m_symbol.GetFullPinCount(), m_fields );
|
m_libraryModelsMgr.CreateModel( baseModel, sourcePins, m_fields );
|
||||||
else
|
else
|
||||||
m_libraryModelsMgr.CreateModel( baseModel, m_symbol.GetFullPinCount() );
|
m_libraryModelsMgr.CreateModel( baseModel, sourcePins );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& e )
|
catch( const IO_ERROR& e )
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_utils.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <sch_symbol.h>
|
#include <sch_symbol.h>
|
||||||
|
@ -143,31 +144,35 @@ SIM_LIBRARY& SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER* aR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL& SIM_LIB_MGR::CreateModel( SIM_MODEL::TYPE aType, int aSymbolPinCount )
|
SIM_MODEL& SIM_LIB_MGR::CreateModel( SIM_MODEL::TYPE aType, const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
m_models.push_back( SIM_MODEL::Create( aType, aSymbolPinCount ) );
|
m_models.push_back( SIM_MODEL::Create( aType, aPins ) );
|
||||||
return *m_models.back();
|
return *m_models.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int aSymbolPinCount )
|
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
m_models.push_back( SIM_MODEL::Create( aBaseModel, aSymbolPinCount ) );
|
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins ) );
|
||||||
return *m_models.back();
|
return *m_models.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int aSymbolPinCount,
|
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<T>& aFields )
|
const std::vector<T>& aFields )
|
||||||
{
|
{
|
||||||
m_models.push_back( SIM_MODEL::Create( aBaseModel, aSymbolPinCount, aFields ) );
|
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins, aFields ) );
|
||||||
return *m_models.back();
|
return *m_models.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int aSymbolPinCount,
|
template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<SCH_FIELD>& aFields );
|
const std::vector<SCH_FIELD>& aFields );
|
||||||
template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int aSymbolPinCount,
|
template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<LIB_FIELD>& aFields );
|
const std::vector<LIB_FIELD>& aFields );
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,37 +225,47 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateModel( fields, static_cast<int>( aSymbol.GetRawPins().size() ) );
|
std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins();
|
||||||
|
|
||||||
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
||||||
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
||||||
|
{
|
||||||
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
return CreateModel( fields, sourcePins );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<T>& aFields, int aSymbolPinCount )
|
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<T>& aFields,
|
||||||
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
std::string libraryPath = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::LIBRARY_FIELD );
|
std::string libraryPath = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::LIBRARY_FIELD );
|
||||||
std::string baseModelName = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::NAME_FIELD );
|
std::string baseModelName = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::NAME_FIELD );
|
||||||
|
|
||||||
if( libraryPath != "" )
|
if( libraryPath != "" )
|
||||||
{
|
{
|
||||||
return CreateModel( libraryPath, baseModelName, aFields, aSymbolPinCount );
|
return CreateModel( libraryPath, baseModelName, aFields, aPins );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_models.push_back( SIM_MODEL::Create( aSymbolPinCount, aFields ) );
|
m_models.push_back( SIM_MODEL::Create( aFields, aPins ) );
|
||||||
return { baseModelName, *m_models.back() };
|
return { baseModelName, *m_models.back() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<SCH_FIELD>& aFields,
|
template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<SCH_FIELD>& aFields,
|
||||||
int aSymbolPinCount );
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<LIB_FIELD>& aFields,
|
template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<LIB_FIELD>& aFields,
|
||||||
int aSymbolPinCount );
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
|
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
|
||||||
const std::string& aBaseModelName,
|
const std::string& aBaseModelName,
|
||||||
const std::vector<T>& aFields,
|
const std::vector<T>& aFields,
|
||||||
int aSymbolPinCount )
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
|
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
|
||||||
SIM_LIBRARY* library = nullptr;
|
SIM_LIBRARY* library = nullptr;
|
||||||
|
@ -286,7 +301,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
|
||||||
path ) );
|
path ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_models.push_back( SIM_MODEL::Create( *baseModel, aSymbolPinCount, aFields ) );
|
m_models.push_back( SIM_MODEL::Create( *baseModel, aPins, aFields ) );
|
||||||
|
|
||||||
return { aBaseModelName, *m_models.back() };
|
return { aBaseModelName, *m_models.back() };
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,23 +48,26 @@ public:
|
||||||
SIM_LIBRARY& AddLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
|
SIM_LIBRARY& AddLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
|
||||||
SIM_LIBRARY& SetLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
|
SIM_LIBRARY& SetLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
|
||||||
|
|
||||||
SIM_MODEL& CreateModel( SIM_MODEL::TYPE aType, int aSymbolPinCount );
|
SIM_MODEL& CreateModel( SIM_MODEL::TYPE aType, const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
SIM_MODEL& CreateModel( const SIM_MODEL& aBaseModel, int aSymbolPinCount );
|
SIM_MODEL& CreateModel( const SIM_MODEL& aBaseModel, const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SIM_MODEL& CreateModel( const SIM_MODEL& aBaseModel, int aSymbolPinCount,
|
SIM_MODEL& CreateModel( const SIM_MODEL& aBaseModel, const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<T>& aFields );
|
const std::vector<T>& aFields );
|
||||||
|
|
||||||
// TODO: The argument can be made const.
|
// TODO: The argument can be made const.
|
||||||
SIM_LIBRARY::MODEL CreateModel( const SCH_SHEET_PATH* aSheetPath, SCH_SYMBOL& aSymbol );
|
SIM_LIBRARY::MODEL CreateModel( const SCH_SHEET_PATH* aSheetPath, SCH_SYMBOL& aSymbol );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SIM_LIBRARY::MODEL CreateModel( const std::vector<T>& aFields, int aSymbolPinCount );
|
SIM_LIBRARY::MODEL CreateModel( const std::vector<T>& aFields,
|
||||||
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SIM_LIBRARY::MODEL CreateModel( const wxString& aLibraryPath, const std::string& aBaseModelName,
|
SIM_LIBRARY::MODEL CreateModel( const wxString& aLibraryPath,
|
||||||
const std::vector<T>& aFields, int aSymbolPinCount );
|
const std::string& aBaseModelName,
|
||||||
|
const std::vector<T>& aFields,
|
||||||
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
void SetModel( int aIndex, std::unique_ptr<SIM_MODEL> aModel );
|
void SetModel( int aIndex, std::unique_ptr<SIM_MODEL> aModel );
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <locale_io.h>
|
#include <locale_io.h>
|
||||||
#include <pegtl.hpp>
|
#include <pegtl.hpp>
|
||||||
#include <pegtl/contrib/parse_tree.hpp>
|
#include <pegtl/contrib/parse_tree.hpp>
|
||||||
|
#include <lib_pin.h>
|
||||||
|
|
||||||
|
|
||||||
void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
|
void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
|
||||||
|
@ -36,16 +37,17 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
|
||||||
m_kibis = KIBIS( aFilePath, m_reporter );
|
m_kibis = KIBIS( aFilePath, m_reporter );
|
||||||
|
|
||||||
if( !m_kibis.m_valid )
|
if( !m_kibis.m_valid )
|
||||||
{
|
|
||||||
THROW_IO_ERROR( wxString::Format( "Invalid ibis file" ) );
|
THROW_IO_ERROR( wxString::Format( "Invalid ibis file" ) );
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned pinNumber = 2;
|
LIB_PIN pinA( nullptr );
|
||||||
|
LIB_PIN pinB( nullptr );
|
||||||
|
pinA.SetNumber( wxT( "1" ) );
|
||||||
|
pinB.SetNumber( wxT( "2" ) );
|
||||||
|
std::vector<LIB_PIN*> pins = { &pinA, &pinB };
|
||||||
|
|
||||||
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
||||||
{
|
{
|
||||||
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pinNumber ) );
|
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins ) );
|
||||||
m_modelNames.emplace_back( kcomp.m_name );
|
m_modelNames.emplace_back( kcomp.m_name );
|
||||||
|
|
||||||
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
|
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
|
||||||
|
|
|
@ -179,7 +179,7 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||||
case TYPE::NMOS_HISIMHV2: return { DEVICE_T::NMOS, "HISIMHV2", "HiSIM_HV2" };
|
case TYPE::NMOS_HISIMHV2: return { DEVICE_T::NMOS, "HISIMHV2", "HiSIM_HV2" };
|
||||||
case TYPE::PMOS_HISIMHV2: return { DEVICE_T::PMOS, "HISIMHV2", "HiSIM_HV2" };
|
case TYPE::PMOS_HISIMHV2: return { DEVICE_T::PMOS, "HISIMHV2", "HiSIM_HV2" };
|
||||||
|
|
||||||
case TYPE::V: return { DEVICE_T::V, "", "DC", };
|
case TYPE::V: return { DEVICE_T::V, "DC", "DC", };
|
||||||
case TYPE::V_SIN: return { DEVICE_T::V, "SIN", "Sine" };
|
case TYPE::V_SIN: return { DEVICE_T::V, "SIN", "Sine" };
|
||||||
case TYPE::V_PULSE: return { DEVICE_T::V, "PULSE", "Pulse" };
|
case TYPE::V_PULSE: return { DEVICE_T::V, "PULSE", "Pulse" };
|
||||||
case TYPE::V_EXP: return { DEVICE_T::V, "EXP", "Exponential" };
|
case TYPE::V_EXP: return { DEVICE_T::V, "EXP", "Exponential" };
|
||||||
|
@ -195,7 +195,7 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||||
//case TYPE::V_RANDPOISSON: return { DEVICE_TYPE::V, "RANDPOISSON", "Random Poisson" };
|
//case TYPE::V_RANDPOISSON: return { DEVICE_TYPE::V, "RANDPOISSON", "Random Poisson" };
|
||||||
case TYPE::V_BEHAVIORAL: return { DEVICE_T::V, "=", "Behavioral" };
|
case TYPE::V_BEHAVIORAL: return { DEVICE_T::V, "=", "Behavioral" };
|
||||||
|
|
||||||
case TYPE::I: return { DEVICE_T::I, "", "DC", };
|
case TYPE::I: return { DEVICE_T::I, "DC", "DC", };
|
||||||
case TYPE::I_SIN: return { DEVICE_T::I, "SIN", "Sine" };
|
case TYPE::I_SIN: return { DEVICE_T::I, "SIN", "Sine" };
|
||||||
case TYPE::I_PULSE: return { DEVICE_T::I, "PULSE", "Pulse" };
|
case TYPE::I_PULSE: return { DEVICE_T::I, "PULSE", "Pulse" };
|
||||||
case TYPE::I_EXP: return { DEVICE_T::I, "EXP", "Exponential" };
|
case TYPE::I_EXP: return { DEVICE_T::I, "EXP", "Exponential" };
|
||||||
|
@ -312,12 +312,12 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||||
case TYPE::NMOS_HISIMHV2: return { "M", "NMOS", "", "73", true, false, "2.2.0" };
|
case TYPE::NMOS_HISIMHV2: return { "M", "NMOS", "", "73", true, false, "2.2.0" };
|
||||||
case TYPE::PMOS_HISIMHV2: return { "M", "PMOS", "", "73", true, false, "2.2.0" };
|
case TYPE::PMOS_HISIMHV2: return { "M", "PMOS", "", "73", true, false, "2.2.0" };
|
||||||
|
|
||||||
case TYPE::V: return { "V", "" };
|
case TYPE::V: return { "V", "", "DC" };
|
||||||
case TYPE::V_SIN: return { "V", "", "SIN" };
|
case TYPE::V_SIN: return { "V", "", "SIN" };
|
||||||
case TYPE::V_PULSE: return { "V", "", "PULSE" };
|
case TYPE::V_PULSE: return { "V", "", "PULSE" };
|
||||||
case TYPE::V_EXP: return { "V", "", "EXP" };
|
case TYPE::V_EXP: return { "V", "", "EXP" };
|
||||||
/*case TYPE::V_SFAM: return { "V", "", "AM" };
|
//case TYPE::V_SFAM: return { "V", "", "AM" };
|
||||||
case TYPE::V_SFFM: return { "V", "", "SFFM" };*/
|
//case TYPE::V_SFFM: return { "V", "", "SFFM" };
|
||||||
case TYPE::V_PWL: return { "V", "", "PWL" };
|
case TYPE::V_PWL: return { "V", "", "PWL" };
|
||||||
case TYPE::V_WHITENOISE: return { "V", "", "TRNOISE" };
|
case TYPE::V_WHITENOISE: return { "V", "", "TRNOISE" };
|
||||||
case TYPE::V_PINKNOISE: return { "V", "", "TRNOISE" };
|
case TYPE::V_PINKNOISE: return { "V", "", "TRNOISE" };
|
||||||
|
@ -328,12 +328,12 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||||
//case TYPE::V_RANDPOISSON: return { "V", "", "TRRANDOM" };
|
//case TYPE::V_RANDPOISSON: return { "V", "", "TRRANDOM" };
|
||||||
case TYPE::V_BEHAVIORAL: return { "B" };
|
case TYPE::V_BEHAVIORAL: return { "B" };
|
||||||
|
|
||||||
case TYPE::I: return { "I", "" };
|
case TYPE::I: return { "I", "", "DC" };
|
||||||
case TYPE::I_PULSE: return { "I", "", "PULSE" };
|
case TYPE::I_PULSE: return { "I", "", "PULSE" };
|
||||||
case TYPE::I_SIN: return { "I", "", "SIN" };
|
case TYPE::I_SIN: return { "I", "", "SIN" };
|
||||||
case TYPE::I_EXP: return { "I", "", "EXP" };
|
case TYPE::I_EXP: return { "I", "", "EXP" };
|
||||||
/*case TYPE::I_SFAM: return { "V", "", "AM" };
|
//case TYPE::I_SFAM: return { "V", "", "AM" };
|
||||||
case TYPE::I_SFFM: return { "V", "", "SFFM" };*/
|
//case TYPE::I_SFFM: return { "V", "", "SFFM" };
|
||||||
case TYPE::I_PWL: return { "I", "", "PWL" };
|
case TYPE::I_PWL: return { "I", "", "PWL" };
|
||||||
case TYPE::I_WHITENOISE: return { "I", "", "TRNOISE" };
|
case TYPE::I_WHITENOISE: return { "I", "", "TRNOISE" };
|
||||||
case TYPE::I_PINKNOISE: return { "I", "", "TRNOISE" };
|
case TYPE::I_PINKNOISE: return { "I", "", "TRNOISE" };
|
||||||
|
@ -412,83 +412,62 @@ TYPE SIM_MODEL::InferTypeFromLegacyFields( const std::vector<T>& aFields )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields )
|
|
||||||
{
|
|
||||||
doReadDataFields( aSymbolPinCount, aFields );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields )
|
void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields )
|
||||||
{
|
{
|
||||||
ReadDataSchFields( aSymbolPinCount, aFields );
|
doReadDataFields( aSymbolPinCount, aFields );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields )
|
void SIM_MODEL::ReadDataFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields )
|
||||||
{
|
|
||||||
ReadDataLibFields( aSymbolPinCount, aFields );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL::ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields )
|
|
||||||
{
|
{
|
||||||
doReadDataFields( aSymbolPinCount, aFields );
|
doReadDataFields( aSymbolPinCount, aFields );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL::ReadDataLibFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields )
|
template <>
|
||||||
|
void SIM_MODEL::ReadDataFields( const std::vector<SCH_FIELD>* aFields,
|
||||||
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
doReadDataFields( aSymbolPinCount, aFields );
|
doReadDataFields( aFields, aPins );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <>
|
||||||
void SIM_MODEL::WriteFields( std::vector<T>& aFields ) const
|
void SIM_MODEL::ReadDataFields( const std::vector<LIB_FIELD>* aFields,
|
||||||
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
doWriteFields( aFields );
|
doReadDataFields( aFields, aPins );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void SIM_MODEL::WriteFields( std::vector<SCH_FIELD>& aFields ) const
|
void SIM_MODEL::WriteFields( std::vector<SCH_FIELD>& aFields ) const
|
||||||
{
|
{
|
||||||
WriteDataSchFields( aFields );
|
doWriteFields( aFields );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void SIM_MODEL::WriteFields( std::vector<LIB_FIELD>& aFields ) const
|
void SIM_MODEL::WriteFields( std::vector<LIB_FIELD>& aFields ) const
|
||||||
{
|
|
||||||
WriteDataLibFields( aFields );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL::WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const
|
|
||||||
{
|
{
|
||||||
doWriteFields( aFields );
|
doWriteFields( aFields );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const
|
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
|
||||||
doWriteFields( aFields );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, unsigned aSymbolPinCount )
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<SIM_MODEL> model = Create( aType );
|
std::unique_ptr<SIM_MODEL> model = Create( aType );
|
||||||
|
|
||||||
// Passing nullptr to ReadDataFields will make it act as if all fields were empty.
|
// Passing nullptr to ReadDataFields will make it act as if all fields were empty.
|
||||||
model->ReadDataFields( aSymbolPinCount, static_cast<const std::vector<void>*>( nullptr ) );
|
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount )
|
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins)
|
||||||
{
|
{
|
||||||
std::unique_ptr<SIM_MODEL> model = Create( aBaseModel.GetType() );
|
std::unique_ptr<SIM_MODEL> model = Create( aBaseModel.GetType() );
|
||||||
|
|
||||||
|
@ -501,13 +480,14 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsig
|
||||||
DisplayErrorMessage( nullptr, err.What() );
|
DisplayErrorMessage( nullptr, err.What() );
|
||||||
}
|
}
|
||||||
|
|
||||||
model->ReadDataFields( aSymbolPinCount, static_cast<const std::vector<void>*>( nullptr ) );
|
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount,
|
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<T>& aFields )
|
const std::vector<T>& aFields )
|
||||||
{
|
{
|
||||||
TYPE type = ReadTypeFromFields( aFields );
|
TYPE type = ReadTypeFromFields( aFields );
|
||||||
|
@ -526,34 +506,35 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsig
|
||||||
{
|
{
|
||||||
DisplayErrorMessage( nullptr, err.What() );
|
DisplayErrorMessage( nullptr, err.What() );
|
||||||
}
|
}
|
||||||
model->ReadDataFields( aSymbolPinCount, &aFields );
|
|
||||||
|
model->ReadDataFields( &aFields, aPins );
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
||||||
unsigned aSymbolPinCount,
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<SCH_FIELD>& aFields );
|
const std::vector<SCH_FIELD>& aFields );
|
||||||
|
|
||||||
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
||||||
unsigned aSymbolPinCount,
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<LIB_FIELD>& aFields );
|
const std::vector<LIB_FIELD>& aFields );
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( unsigned aSymbolPinCount,
|
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
||||||
const std::vector<T>& aFields )
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
{
|
{
|
||||||
TYPE type = ReadTypeFromFields( aFields );
|
TYPE type = ReadTypeFromFields( aFields );
|
||||||
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
||||||
|
|
||||||
model->ReadDataFields( aSymbolPinCount, &aFields );
|
model->ReadDataFields( &aFields, aPins );
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( unsigned aSymbolPinCount,
|
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<SCH_FIELD>& aFields,
|
||||||
const std::vector<SCH_FIELD>& aFields );
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( unsigned aSymbolPinCount,
|
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<LIB_FIELD>& aFields,
|
||||||
const std::vector<LIB_FIELD>& aFields );
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -619,12 +600,21 @@ void SIM_MODEL::SetFieldValue( std::vector<T>& aFields, const std::string& aFiel
|
||||||
aFields.emplace_back( wxPoint(), aFields.size(), parent, aFieldName );
|
aFields.emplace_back( wxPoint(), aFields.size(), parent, aFieldName );
|
||||||
}
|
}
|
||||||
else if constexpr( std::is_same<T, LIB_FIELD>::value )
|
else if constexpr( std::is_same<T, LIB_FIELD>::value )
|
||||||
|
{
|
||||||
aFields.emplace_back( aFields.size(), aFieldName );
|
aFields.emplace_back( aFields.size(), aFieldName );
|
||||||
|
}
|
||||||
|
|
||||||
aFields.back().SetText( aValue );
|
aFields.back().SetText( aValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template void SIM_MODEL::SetFieldValue<SCH_FIELD>( std::vector<SCH_FIELD>& aFields,
|
||||||
|
const std::string& aFieldName,
|
||||||
|
const std::string& aValue );
|
||||||
|
template void SIM_MODEL::SetFieldValue<LIB_FIELD>( std::vector<LIB_FIELD>& aFields,
|
||||||
|
const std::string& aFieldName,
|
||||||
|
const std::string& aValue );
|
||||||
|
|
||||||
SIM_MODEL::~SIM_MODEL() = default;
|
SIM_MODEL::~SIM_MODEL() = default;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1012,9 +1002,39 @@ void SIM_MODEL::CreatePins( unsigned aSymbolPinCount )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SIM_MODEL::CreatePins( const std::vector<LIB_PIN*> aSymbolPins )
|
||||||
|
{
|
||||||
|
// Default pin sequence: model pins are the same as symbol pins.
|
||||||
|
// Excess model pins are set as Not Connected.
|
||||||
|
// Note that intentionally nothing is added if `getPinNames()` returns an empty vector.
|
||||||
|
|
||||||
|
// SIM_MODEL pins must be ordered by symbol pin numbers -- this is assumed by the code that
|
||||||
|
// accesses them.
|
||||||
|
|
||||||
|
for( unsigned modelPinIndex = 0; modelPinIndex < getPinNames().size(); ++modelPinIndex )
|
||||||
|
{
|
||||||
|
if( modelPinIndex < aSymbolPins.size() )
|
||||||
|
{
|
||||||
|
AddPin( { getPinNames().at( modelPinIndex ),
|
||||||
|
aSymbolPins[ modelPinIndex ]->GetNumber().ToStdString() } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddPin( { getPinNames().at( modelPinIndex ), "" } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: remove this API. If we have symbol fields, then we have symbol pins and we should be
|
||||||
|
// creating a model with the real symbol pin names, not indexes...
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SIM_MODEL::doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields )
|
void SIM_MODEL::doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields )
|
||||||
{
|
{
|
||||||
|
bool diffMode = GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
||||||
|
SwitchSingleEndedDiff( diffMode );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_serde->ParseEnable( GetFieldValue( aFields, ENABLE_FIELD ) );
|
m_serde->ParseEnable( GetFieldValue( aFields, ENABLE_FIELD ) );
|
||||||
|
@ -1034,6 +1054,32 @@ void SIM_MODEL::doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void SIM_MODEL::doReadDataFields( const std::vector<T>* aFields,
|
||||||
|
const std::vector<LIB_PIN*>& aPins )
|
||||||
|
{
|
||||||
|
bool diffMode = GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
||||||
|
SwitchSingleEndedDiff( diffMode );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_serde->ParseEnable( GetFieldValue( aFields, ENABLE_FIELD ) );
|
||||||
|
|
||||||
|
CreatePins( aPins );
|
||||||
|
m_serde->ParsePins( GetFieldValue( aFields, PINS_FIELD ) );
|
||||||
|
|
||||||
|
std::string paramsField = GetFieldValue( aFields, PARAMS_FIELD );
|
||||||
|
|
||||||
|
if( !m_serde->ParseParams( paramsField ) )
|
||||||
|
m_serde->ParseValue( GetFieldValue( aFields, VALUE_FIELD ) );
|
||||||
|
}
|
||||||
|
catch( IO_ERROR& err )
|
||||||
|
{
|
||||||
|
DisplayErrorMessage( nullptr, err.What() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SIM_MODEL::doWriteFields( std::vector<T>& aFields ) const
|
void SIM_MODEL::doWriteFields( std::vector<T>& aFields ) const
|
||||||
{
|
{
|
||||||
|
@ -1173,9 +1219,6 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString prefix = aSymbol.GetPrefix();
|
|
||||||
T_field* valueField = aSymbol.FindField( wxT( "Value" ) );
|
|
||||||
|
|
||||||
auto getSIValue =
|
auto getSIValue =
|
||||||
[]( T_field* aField )
|
[]( T_field* aField )
|
||||||
{
|
{
|
||||||
|
@ -1191,13 +1234,23 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
wxString spiceType;
|
wxString prefix = aSymbol.GetPrefix();
|
||||||
|
T_field* valueField = aSymbol.FindField( wxT( "Value" ) );
|
||||||
|
std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins();
|
||||||
|
|
||||||
|
std::sort( sourcePins.begin(), sourcePins.end(),
|
||||||
|
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
||||||
|
{
|
||||||
|
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
wxString spiceDeviceType;
|
||||||
wxString spiceModel;
|
wxString spiceModel;
|
||||||
|
wxString spiceType;
|
||||||
wxString spiceLib;
|
wxString spiceLib;
|
||||||
wxString pinMap;
|
wxString pinMap;
|
||||||
wxString spiceParams;
|
wxString spiceParams;
|
||||||
bool modelFromValueField = false;
|
bool modelFromValueField = false;
|
||||||
bool modelFromLib = false;
|
|
||||||
|
|
||||||
if( aSymbol.FindField( wxT( "Spice_Primitive" ) )
|
if( aSymbol.FindField( wxT( "Spice_Primitive" ) )
|
||||||
|| aSymbol.FindField( wxT( "Spice_Node_Sequence" ) )
|
|| aSymbol.FindField( wxT( "Spice_Node_Sequence" ) )
|
||||||
|
@ -1207,7 +1260,7 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
{
|
{
|
||||||
if( T_field* primitiveField = aSymbol.FindField( wxT( "Spice_Primitive" ) ) )
|
if( T_field* primitiveField = aSymbol.FindField( wxT( "Spice_Primitive" ) ) )
|
||||||
{
|
{
|
||||||
spiceType = primitiveField->GetText();
|
spiceDeviceType = primitiveField->GetText();
|
||||||
aSymbol.RemoveField( primitiveField );
|
aSymbol.RemoveField( primitiveField );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,7 +1290,7 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
|
|
||||||
if( T_field* modelField = aSymbol.FindField( wxT( "Spice_Model" ) ) )
|
if( T_field* modelField = aSymbol.FindField( wxT( "Spice_Model" ) ) )
|
||||||
{
|
{
|
||||||
spiceModel = modelField->GetText();
|
spiceModel = getSIValue( modelField );
|
||||||
aSymbol.RemoveField( modelField );
|
aSymbol.RemoveField( modelField );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1267,14 +1320,8 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
{
|
{
|
||||||
spiceLib = libFileField->GetText();
|
spiceLib = libFileField->GetText();
|
||||||
aSymbol.RemoveField( libFileField );
|
aSymbol.RemoveField( libFileField );
|
||||||
modelFromLib = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( prefix == wxT( "V" ) || prefix == wxT( "I" ) )
|
|
||||||
{
|
|
||||||
spiceModel = getSIValue( valueField );
|
|
||||||
modelFromValueField = true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Auto convert some legacy fields used in the middle of 7.0 development...
|
// Auto convert some legacy fields used in the middle of 7.0 development...
|
||||||
|
@ -1300,8 +1347,6 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
|
|
||||||
wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' );
|
wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' );
|
||||||
|
|
||||||
std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins();
|
|
||||||
|
|
||||||
if( isPassive && pinIndexes.size() == 2 && sourcePins.size() == 2 )
|
if( isPassive && pinIndexes.size() == 2 && sourcePins.size() == 2 )
|
||||||
{
|
{
|
||||||
if( pinIndexes[0] == wxT( "2" ) )
|
if( pinIndexes[0] == wxT( "2" ) )
|
||||||
|
@ -1342,7 +1387,10 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( modelFromLib )
|
bool libraryModel = false;
|
||||||
|
bool internalModel = false;
|
||||||
|
|
||||||
|
if( !spiceLib.IsEmpty() )
|
||||||
{
|
{
|
||||||
SIM_LIB_MGR libMgr( aProject );
|
SIM_LIB_MGR libMgr( aProject );
|
||||||
|
|
||||||
|
@ -1350,18 +1398,78 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
{
|
{
|
||||||
std::vector<T_field> emptyFields;
|
std::vector<T_field> emptyFields;
|
||||||
SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLib, spiceModel.ToStdString(),
|
SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLib, spiceModel.ToStdString(),
|
||||||
emptyFields, aSymbol.GetFullPinCount() );
|
emptyFields, sourcePins );
|
||||||
|
|
||||||
spiceParams = wxString( model.model.GetBaseModel()->Serde().GenerateParams() );
|
spiceParams = wxString( model.model.GetBaseModel()->Serde().GenerateParams() );
|
||||||
|
libraryModel = true;
|
||||||
|
|
||||||
|
if( pinMap.IsEmpty() )
|
||||||
|
{
|
||||||
|
// Generate a default pin map
|
||||||
|
model.model.CreatePins( sourcePins );
|
||||||
|
pinMap = wxString( model.model.Serde().GeneratePins() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
{
|
{
|
||||||
// Fall back to raw spice model
|
// Fall back to raw spice model
|
||||||
modelFromLib = false;
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Convert functional SPICE model syntax to name=value pairs. For instance, "dc(1)"
|
||||||
|
// needs to go to "dc=1", while "sin(0, 1, 60)" needs to go to "dc=0 ampl=1 f=60".
|
||||||
|
|
||||||
|
wxRegEx regex( wxT( "^[a-z]+\\(.*\\)$" ) );
|
||||||
|
|
||||||
|
if( regex.Matches( spiceModel ) )
|
||||||
|
{
|
||||||
|
wxString paramSet;
|
||||||
|
|
||||||
|
spiceType = spiceModel.BeforeFirst( '(', ¶mSet );
|
||||||
|
paramSet = paramSet.BeforeLast( ')' );
|
||||||
|
|
||||||
|
wxStringTokenizer tokenizer( paramSet, wxT( " " ), wxTOKEN_STRTOK );
|
||||||
|
|
||||||
|
spiceType.MakeUpper();
|
||||||
|
|
||||||
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||||
|
{
|
||||||
|
if( spiceDeviceType == SIM_MODEL::SpiceInfo( type ).itemType
|
||||||
|
&& spiceType == SIM_MODEL::SpiceInfo( type ).inlineTypeString )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
||||||
|
|
||||||
|
for( int ii = 0; tokenizer.HasMoreTokens(); ++ii )
|
||||||
|
{
|
||||||
|
model->SetParamValue( ii, tokenizer.GetNextToken().ToStdString(),
|
||||||
|
SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||||
|
}
|
||||||
|
|
||||||
|
spiceParams = wxString( model->Serde().GenerateParams() );
|
||||||
|
internalModel = true;
|
||||||
|
|
||||||
|
if( pinMap.IsEmpty() )
|
||||||
|
{
|
||||||
|
// Generate a default pin map
|
||||||
|
model->CreatePins( sourcePins );
|
||||||
|
pinMap = wxString( model->Serde().GeneratePins() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( ... )
|
||||||
|
{
|
||||||
|
// Fall back to raw spice model
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( modelFromLib )
|
if( libraryModel )
|
||||||
{
|
{
|
||||||
T_field libraryField( &aSymbol, -1, SIM_MODEL::LIBRARY_FIELD );
|
T_field libraryField( &aSymbol, -1, SIM_MODEL::LIBRARY_FIELD );
|
||||||
libraryField.SetText( spiceLib );
|
libraryField.SetText( spiceLib );
|
||||||
|
@ -1378,18 +1486,33 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
if( modelFromValueField )
|
if( modelFromValueField )
|
||||||
valueField->SetText( wxT( "${SIM.NAME}" ) );
|
valueField->SetText( wxT( "${SIM.NAME}" ) );
|
||||||
}
|
}
|
||||||
else
|
else if( internalModel )
|
||||||
{
|
{
|
||||||
// Insert a raw spice model as a substitute.
|
T_field deviceTypeField( &aSymbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||||
|
deviceTypeField.SetText( spiceDeviceType );
|
||||||
|
aSymbol.AddField( deviceTypeField );
|
||||||
|
|
||||||
if( spiceType.IsEmpty() && spiceLib.IsEmpty() )
|
T_field typeField( &aSymbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||||
|
typeField.SetText( spiceType );
|
||||||
|
aSymbol.AddField( typeField );
|
||||||
|
|
||||||
|
T_field paramsField( &aSymbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||||
|
paramsField.SetText( spiceParams );
|
||||||
|
aSymbol.AddField( paramsField );
|
||||||
|
|
||||||
|
if( modelFromValueField )
|
||||||
|
valueField->SetText( wxT( "${SIM.PARAMS}" ) );
|
||||||
|
}
|
||||||
|
else // Insert a raw spice model as a substitute.
|
||||||
|
{
|
||||||
|
if( spiceDeviceType.IsEmpty() && spiceLib.IsEmpty() )
|
||||||
{
|
{
|
||||||
spiceParams = spiceModel;
|
spiceParams = spiceModel;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spiceParams.Printf( wxT( "type=\"%s\" model=\"%s\" lib=\"%s\"" ),
|
spiceParams.Printf( wxT( "type=\"%s\" model=\"%s\" lib=\"%s\"" ),
|
||||||
spiceType, spiceModel, spiceLib );
|
spiceDeviceType, spiceModel, spiceLib );
|
||||||
}
|
}
|
||||||
|
|
||||||
T_field deviceTypeField( &aSymbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
T_field deviceTypeField( &aSymbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||||
|
@ -1408,27 +1531,10 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
if( valueField )
|
if( valueField )
|
||||||
valueField->SetText( wxT( "${SIM.PARAMS}" ) );
|
valueField->SetText( wxT( "${SIM.PARAMS}" ) );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( !pinMap.IsEmpty() )
|
if( pinMap.IsEmpty() )
|
||||||
{
|
{
|
||||||
T_field pinsField( &aSymbol, -1, SIM_MODEL::PINS_FIELD );
|
// Generate a 1:1 pin map. We don't know the SPICE model pinNames, so just use indexes.
|
||||||
|
|
||||||
pinsField.SetText( pinMap );
|
|
||||||
aSymbol.AddField( pinsField );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Generate a 1:1 pin map. We don't necessarily know the SPICE model pinNames, so just
|
|
||||||
// use indexes.
|
|
||||||
std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins();
|
|
||||||
|
|
||||||
std::sort( sourcePins.begin(), sourcePins.end(),
|
|
||||||
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
|
|
||||||
{
|
|
||||||
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
|
|
||||||
} );
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < sourcePins.size(); ++ii )
|
for( unsigned ii = 0; ii < sourcePins.size(); ++ii )
|
||||||
{
|
{
|
||||||
if( ii > 0 )
|
if( ii > 0 )
|
||||||
|
@ -1438,12 +1544,13 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
||||||
sourcePins[ii]->GetNumber(),
|
sourcePins[ii]->GetNumber(),
|
||||||
ii + 1 ) );
|
ii + 1 ) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
T_field pinsField( &aSymbol, aSymbol.GetFieldCount(), SIM_MODEL::PINS_FIELD );
|
T_field pinsField( &aSymbol, -1, SIM_MODEL::PINS_FIELD );
|
||||||
pinsField.SetText( pinMap );
|
pinsField.SetText( pinMap );
|
||||||
aSymbol.AddField( pinsField );
|
aSymbol.AddField( pinsField );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template void SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( SCH_SYMBOL& aSymbol,
|
template void SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( SCH_SYMBOL& aSymbol,
|
||||||
|
|
|
@ -400,16 +400,19 @@ public:
|
||||||
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
||||||
|
|
||||||
|
|
||||||
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, unsigned aSymbolPinCount );
|
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, const std::vector<LIB_PIN*>& aPins );
|
||||||
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount );
|
|
||||||
|
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount,
|
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel,
|
||||||
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
const std::vector<T>& aFields );
|
const std::vector<T>& aFields );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::unique_ptr<SIM_MODEL> Create( unsigned aSymbolPinCount,
|
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields,
|
||||||
const std::vector<T>& aFields );
|
const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName );
|
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName );
|
||||||
|
@ -433,18 +436,12 @@ public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
void ReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||||
|
|
||||||
virtual void ReadDataSchFields( unsigned aSymbolPinCount,
|
template <typename T>
|
||||||
const std::vector<SCH_FIELD>* aFields );
|
void ReadDataFields( const std::vector<T>* aFields, const std::vector<LIB_PIN*>& aPins );
|
||||||
virtual void ReadDataLibFields( unsigned aSymbolPinCount,
|
|
||||||
const std::vector<LIB_FIELD>* aFields );
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteFields( std::vector<T>& aFields ) const;
|
void WriteFields( std::vector<T>& aFields ) const;
|
||||||
|
|
||||||
virtual void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const;
|
|
||||||
virtual void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const;
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool HasToIncludeSpiceLibrary() const { return GetBaseModel() && !HasOverrides(); }
|
virtual bool HasToIncludeSpiceLibrary() const { return GetBaseModel() && !HasOverrides(); }
|
||||||
|
|
||||||
SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); }
|
SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); }
|
||||||
|
@ -522,6 +519,8 @@ public:
|
||||||
}
|
}
|
||||||
bool IsStoredInValue() const { return m_isStoredInValue; }
|
bool IsStoredInValue() const { return m_isStoredInValue; }
|
||||||
|
|
||||||
|
virtual void SwitchSingleEndedDiff( bool aDiff ) { };
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static bool InferPassiveSimModel( T& aSymbol, bool aResolve,
|
static bool InferPassiveSimModel( T& aSymbol, bool aResolve,
|
||||||
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aModelType,
|
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aModelType,
|
||||||
|
@ -539,11 +538,15 @@ protected:
|
||||||
std::unique_ptr<SIM_SERDE> aSerde );
|
std::unique_ptr<SIM_SERDE> aSerde );
|
||||||
|
|
||||||
virtual void CreatePins( unsigned aSymbolPinCount );
|
virtual void CreatePins( unsigned aSymbolPinCount );
|
||||||
|
virtual void CreatePins( const std::vector<LIB_PIN*> aSymbolPins );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
void doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void doReadDataFields( const std::vector<T>* aFields, const std::vector<LIB_PIN*>& aPins );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void doWriteFields( std::vector<T>& aFields ) const;
|
void doWriteFields( std::vector<T>& aFields ) const;
|
||||||
|
|
||||||
|
|
|
@ -499,20 +499,3 @@ std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_KIBIS::makePrbsWaveformParamInfos(
|
||||||
return paramInfos;
|
return paramInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL_KIBIS::ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields )
|
|
||||||
{
|
|
||||||
bool diffMode = SIM_MODEL::GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
|
||||||
SwitchSingleEndedDiff( diffMode );
|
|
||||||
|
|
||||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL_KIBIS::ReadDataLibFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields )
|
|
||||||
{
|
|
||||||
bool diffMode = SIM_MODEL::GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
|
||||||
SwitchSingleEndedDiff( diffMode );
|
|
||||||
|
|
||||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
|
||||||
}
|
|
||||||
|
|
|
@ -87,15 +87,10 @@ public:
|
||||||
|
|
||||||
void SetBaseModel( const SIM_MODEL& aBaseModel ) override;
|
void SetBaseModel( const SIM_MODEL& aBaseModel ) override;
|
||||||
|
|
||||||
void SwitchSingleEndedDiff( bool aDiff );
|
void SwitchSingleEndedDiff( bool aDiff ) override;
|
||||||
bool CanDifferential() const { return m_enableDiff; } ;
|
bool CanDifferential() const { return m_enableDiff; } ;
|
||||||
bool m_enableDiff;
|
bool m_enableDiff;
|
||||||
|
|
||||||
void ReadDataSchFields( unsigned aSymbolPinCount,
|
|
||||||
const std::vector<SCH_FIELD>* aFields ) override;
|
|
||||||
void ReadDataLibFields( unsigned aSymbolPinCount,
|
|
||||||
const std::vector<LIB_FIELD>* aFields ) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CreatePins( unsigned aSymbolPinCount ) override;
|
void CreatePins( unsigned aSymbolPinCount ) override;
|
||||||
|
|
||||||
|
|
|
@ -185,10 +185,14 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.modelName.append( fmt::format( "{}( {})", m_model.GetSpiceInfo().inlineTypeString, args ) );
|
item.modelName.append( fmt::format( "{}( {})",
|
||||||
|
m_model.GetSpiceInfo().inlineTypeString,
|
||||||
|
args ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
item.modelName.append( m_model.GetParam( 0 ).value->ToSpiceString() );
|
item.modelName.append( m_model.GetParam( 0 ).value->ToSpiceString() );
|
||||||
|
}
|
||||||
|
|
||||||
return SPICE_GENERATOR::ItemLine( item );
|
return SPICE_GENERATOR::ItemLine( item );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue