Add Ibis to spice model editor
ADDED: IBIS models are now supported in Sim Model Editor
This commit is contained in:
parent
1a812727cb
commit
528fe4d371
|
@ -275,13 +275,19 @@ set( EESCHEMA_SRCS
|
||||||
sch_plugins/legacy/sch_legacy_plugin_helpers.cpp
|
sch_plugins/legacy/sch_legacy_plugin_helpers.cpp
|
||||||
sch_plugins/database/sch_database_plugin.cpp
|
sch_plugins/database/sch_database_plugin.cpp
|
||||||
|
|
||||||
|
|
||||||
|
${CMAKE_SOURCE_DIR}/pcbnew/ibis/ibis_parser.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/pcbnew/ibis/kibis.cpp
|
||||||
|
|
||||||
# Some simulation features must be built even if libngspice is not linked.
|
# Some simulation features must be built even if libngspice is not linked.
|
||||||
sim/sim_library.cpp
|
sim/sim_library.cpp
|
||||||
sim/sim_library_spice.cpp
|
sim/sim_library_spice.cpp
|
||||||
|
sim/sim_library_kibis.cpp
|
||||||
sim/sim_model.cpp
|
sim/sim_model.cpp
|
||||||
sim/sim_model_behavioral.cpp
|
sim/sim_model_behavioral.cpp
|
||||||
sim/sim_model_ideal.cpp
|
sim/sim_model_ideal.cpp
|
||||||
sim/sim_model_mutual_inductor.cpp
|
sim/sim_model_mutual_inductor.cpp
|
||||||
|
sim/sim_model_kibis.cpp
|
||||||
sim/sim_model_ngspice.cpp
|
sim/sim_model_ngspice.cpp
|
||||||
sim/sim_model_ngspice_data.cpp
|
sim/sim_model_ngspice_data.cpp
|
||||||
sim/sim_model_raw_spice.cpp
|
sim/sim_model_raw_spice.cpp
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#include <dialog_sim_model.h>
|
#include <dialog_sim_model.h>
|
||||||
#include <sim/sim_property.h>
|
#include <sim/sim_property.h>
|
||||||
|
#include <sim/sim_library_kibis.h>
|
||||||
#include <sim/sim_library_spice.h>
|
#include <sim/sim_library_spice.h>
|
||||||
|
#include <sim/sim_model_kibis.h>
|
||||||
#include <sim/sim_model_raw_spice.h>
|
#include <sim/sim_model_raw_spice.h>
|
||||||
#include <widgets/wx_grid.h>
|
#include <widgets/wx_grid.h>
|
||||||
#include <kiplatform/ui.h>
|
#include <kiplatform/ui.h>
|
||||||
|
@ -112,23 +114,63 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol,
|
||||||
|
|
||||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||||
finishDialogSettings();
|
finishDialogSettings();
|
||||||
|
setIbisMode( IsIbisLoaded() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool DIALOG_SIM_MODEL<T>::TransferDataToWindow()
|
bool DIALOG_SIM_MODEL<T>::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
wxString libraryFilename = SIM_MODEL::GetFieldValue( &m_fields,
|
wxString libraryFilename = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::LIBRARY_FIELD );
|
||||||
SIM_LIBRARY_SPICE::LIBRARY_FIELD );
|
|
||||||
|
|
||||||
if( libraryFilename != "" )
|
if( libraryFilename != "" )
|
||||||
{
|
{
|
||||||
// The model is sourced from a library, optionally with instance overrides.
|
// The model is sourced from a library, optionally with instance overrides.
|
||||||
loadLibrary( libraryFilename );
|
loadLibrary( libraryFilename );
|
||||||
|
|
||||||
|
bool ibisMode = IsIbisLoaded();
|
||||||
|
setIbisMode( ibisMode );
|
||||||
|
|
||||||
// Must be set before curModel() is used since the latter checks the combobox value.
|
// Must be set before curModel() is used since the latter checks the combobox value.
|
||||||
m_modelNameCombobox->SetStringSelection(
|
m_modelNameCombobox->SetStringSelection(
|
||||||
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_SPICE::NAME_FIELD ) );
|
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD ) );
|
||||||
|
|
||||||
|
if( ibisMode && ( m_modelNameCombobox->GetSelection() >= 0 ) )
|
||||||
|
{
|
||||||
|
std::shared_ptr<SIM_MODEL_KIBIS> kibismodel =
|
||||||
|
std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
|
||||||
|
m_libraryModels.at( m_modelNameCombobox->GetSelection() ) );
|
||||||
|
|
||||||
|
if( kibismodel )
|
||||||
|
{
|
||||||
|
wxCommandEvent dummyEvent;
|
||||||
|
onModelNameCombobox( dummyEvent ); // refresh list of pins
|
||||||
|
|
||||||
|
long unsigned int i = 0;
|
||||||
|
|
||||||
|
for( std::pair<std::string, std::string> strs : kibismodel->GetIbisPins() )
|
||||||
|
{
|
||||||
|
if( strs.first
|
||||||
|
== SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD ) )
|
||||||
|
{
|
||||||
|
kibismodel->ChangePin(
|
||||||
|
*( std::dynamic_pointer_cast<SIM_LIBRARY_KIBIS>( m_library ) ),
|
||||||
|
strs.first );
|
||||||
|
m_ibisPinCombobox->SetSelection( i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i < kibismodel->GetIbisPins().size() )
|
||||||
|
{
|
||||||
|
onIbisPinCombobox( dummyEvent ); // refresh list of models
|
||||||
|
|
||||||
|
m_ibisModelCombobox->SetStringSelection(
|
||||||
|
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_excludeSymbolCheckbox->SetValue( !curModel().IsEnabled() );
|
m_excludeSymbolCheckbox->SetValue( !curModel().IsEnabled() );
|
||||||
}
|
}
|
||||||
|
@ -169,14 +211,13 @@ bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
|
||||||
|
|
||||||
std::string modelName;
|
std::string modelName;
|
||||||
|
|
||||||
if( m_useLibraryModelRadioButton->GetValue() )
|
modelName = m_modelNameCombobox->GetValue();
|
||||||
modelName = m_modelNameCombobox->GetValue();
|
|
||||||
|
|
||||||
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_SPICE::NAME_FIELD, modelName );
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::NAME_FIELD, modelName );
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
if( m_useLibraryModelRadioButton->GetValue() )
|
if( m_useLibraryModelRadioButton->GetValue() || IsIbisLoaded() )
|
||||||
{
|
{
|
||||||
path = m_library->GetFilePath();
|
path = m_library->GetFilePath();
|
||||||
wxFileName fn( path );
|
wxFileName fn( path );
|
||||||
|
@ -185,7 +226,23 @@ bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
|
||||||
path = fn.GetFullPath();
|
path = fn.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_SPICE::LIBRARY_FIELD, path );
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::LIBRARY_FIELD, path );
|
||||||
|
|
||||||
|
if( IsIbisLoaded() )
|
||||||
|
{
|
||||||
|
std::shared_ptr<SIM_MODEL_KIBIS> kibismodel = std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
|
||||||
|
m_libraryModels.at( m_modelNameCombobox->GetSelection() ) );
|
||||||
|
|
||||||
|
if( kibismodel )
|
||||||
|
|
||||||
|
{
|
||||||
|
SIM_MODEL::SetFieldValue(
|
||||||
|
m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD,
|
||||||
|
kibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first );
|
||||||
|
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
|
||||||
|
std::string( m_ibisModelCombobox->GetValue().c_str() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
curModel().WriteFields( m_fields );
|
curModel().WriteFields( m_fields );
|
||||||
|
|
||||||
|
@ -207,13 +264,15 @@ void DIALOG_SIM_MODEL<T>::updateWidgets()
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||||
{
|
{
|
||||||
if( &curModel() != m_prevModel )
|
if( ( &curModel() != m_prevModel ) || curModel().RequiresUIUpdate() )
|
||||||
{
|
{
|
||||||
SIM_MODEL::DEVICE_TYPE_ deviceType = SIM_MODEL::TypeInfo( curModel().GetType() ).deviceType;
|
SIM_MODEL::DEVICE_TYPE_ deviceType = SIM_MODEL::TypeInfo( curModel().GetType() ).deviceType;
|
||||||
|
|
||||||
// Change the Type choice to match the current device type.
|
// Change the Type choice to match the current device type.
|
||||||
if( !m_prevModel || deviceType != m_prevModel->GetDeviceType() )
|
if( !m_prevModel || deviceType != m_prevModel->GetDeviceType()
|
||||||
|
|| curModel().RequiresUIUpdate() )
|
||||||
{
|
{
|
||||||
|
curModel().UIUpdated();
|
||||||
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
|
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
|
||||||
|
|
||||||
m_typeChoice->Clear();
|
m_typeChoice->Clear();
|
||||||
|
@ -268,6 +327,9 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||||
m_paramGrid->Append( new wxPropertyCategory( "Distributed Quantities" ) );
|
m_paramGrid->Append( new wxPropertyCategory( "Distributed Quantities" ) );
|
||||||
m_paramGrid->HideProperty( "Distributed Quantities" );
|
m_paramGrid->HideProperty( "Distributed Quantities" );
|
||||||
|
|
||||||
|
m_paramGrid->Append( new wxPropertyCategory( "Waveform" ) );
|
||||||
|
m_paramGrid->HideProperty( "Waveform" );
|
||||||
|
|
||||||
m_paramGrid->Append( new wxPropertyCategory( "Limiting Values" ) );
|
m_paramGrid->Append( new wxPropertyCategory( "Limiting Values" ) );
|
||||||
m_paramGrid->HideProperty( "Limiting Values" );
|
m_paramGrid->HideProperty( "Limiting Values" );
|
||||||
|
|
||||||
|
@ -284,6 +346,7 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||||
|
|
||||||
m_paramGrid->CollapseAll();
|
m_paramGrid->CollapseAll();
|
||||||
m_paramGrid->Expand( "AC" );
|
m_paramGrid->Expand( "AC" );
|
||||||
|
m_paramGrid->Expand( "Waveform" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either enable all properties or disable all except the principal ones.
|
// Either enable all properties or disable all except the principal ones.
|
||||||
|
@ -311,10 +374,11 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||||
( *it )->SetValueFromString( prop->GetParam().value->ToString() );
|
( *it )->SetValueFromString( prop->GetParam().value->ToString() );
|
||||||
|
|
||||||
// Most of the values are disabled when the override checkbox is unchecked.
|
// Most of the values are disabled when the override checkbox is unchecked.
|
||||||
( *it )->Enable( m_useInstanceModelRadioButton->GetValue()
|
( *it )->Enable(
|
||||||
|| ( prop->GetParam().info.isInstanceParam
|
( IsIbisLoaded() ) || m_useInstanceModelRadioButton->GetValue()
|
||||||
&& prop->GetParam().info.category == SIM_MODEL::PARAM::CATEGORY::PRINCIPAL )
|
|| ( prop->GetParam().info.isInstanceParam
|
||||||
|| m_overrideCheckbox->GetValue() );
|
&& prop->GetParam().info.category == SIM_MODEL::PARAM::CATEGORY::PRINCIPAL )
|
||||||
|
|| m_overrideCheckbox->GetValue() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +515,13 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
|
||||||
{
|
{
|
||||||
const wxString absolutePath = Prj().AbsolutePath( aFilePath );
|
const wxString absolutePath = Prj().AbsolutePath( aFilePath );
|
||||||
|
|
||||||
|
if( absolutePath.EndsWith( ".ibs" ) )
|
||||||
|
m_library = std::make_shared<SIM_LIBRARY_KIBIS>();
|
||||||
|
else
|
||||||
|
m_library = std::make_shared<SIM_LIBRARY_SPICE>();
|
||||||
|
|
||||||
|
setIbisMode( IsIbisLoaded() );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_library->ReadFile( std::string( absolutePath.ToUTF8() ) );
|
m_library->ReadFile( std::string( absolutePath.ToUTF8() ) );
|
||||||
|
@ -473,11 +544,14 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
|
||||||
{
|
{
|
||||||
const SIM_MODEL& baseModel = m_library->GetModels().at( i );
|
const SIM_MODEL& baseModel = m_library->GetModels().at( i );
|
||||||
wxString baseModelName = m_library->GetModelNames().at( i );
|
wxString baseModelName = m_library->GetModelNames().at( i );
|
||||||
|
wxString expectedModelName;
|
||||||
|
|
||||||
|
expectedModelName =
|
||||||
|
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::NAME_FIELD );
|
||||||
|
|
||||||
// Only the current model is initialized from fields. Others have default
|
// Only the current model is initialized from fields. Others have default
|
||||||
// initialization.
|
// initialization.
|
||||||
if( baseModelName
|
if( baseModelName == expectedModelName )
|
||||||
== SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_SPICE::NAME_FIELD ) )
|
|
||||||
{
|
{
|
||||||
//TODO: it's not cur model.
|
//TODO: it's not cur model.
|
||||||
|
|
||||||
|
@ -500,6 +574,7 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
|
||||||
modelNames.Add( name );
|
modelNames.Add( name );
|
||||||
|
|
||||||
auto validator = dynamic_cast<MODEL_NAME_VALIDATOR*>( m_modelNameCombobox->GetValidator() );
|
auto validator = dynamic_cast<MODEL_NAME_VALIDATOR*>( m_modelNameCombobox->GetValidator() );
|
||||||
|
|
||||||
if( validator )
|
if( validator )
|
||||||
validator->SetIncludes( modelNames );
|
validator->SetIncludes( modelNames );
|
||||||
|
|
||||||
|
@ -547,6 +622,11 @@ void DIALOG_SIM_MODEL<T>::addParamPropertyIfRelevant( int aParamIndex )
|
||||||
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParamIndex ) );
|
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParamIndex ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CATEGORY::WAVEFORM:
|
||||||
|
m_paramGrid->HideProperty( "Waveform", false );
|
||||||
|
m_paramGrid->AppendIn( "Waveform", newParamProperty( aParamIndex ) );
|
||||||
|
break;
|
||||||
|
|
||||||
case CATEGORY::GEOMETRY:
|
case CATEGORY::GEOMETRY:
|
||||||
m_paramGrid->HideProperty( "Geometry", false );
|
m_paramGrid->HideProperty( "Geometry", false );
|
||||||
m_paramGrid->AppendIn( "Geometry", newParamProperty( aParamIndex ) );
|
m_paramGrid->AppendIn( "Geometry", newParamProperty( aParamIndex ) );
|
||||||
|
@ -693,9 +773,7 @@ std::shared_ptr<SIM_MODEL> DIALOG_SIM_MODEL<T>::curModelSharedPtr() const
|
||||||
{
|
{
|
||||||
if( m_useLibraryModelRadioButton->GetValue()
|
if( m_useLibraryModelRadioButton->GetValue()
|
||||||
&& m_modelNameCombobox->GetSelection() != wxNOT_FOUND )
|
&& m_modelNameCombobox->GetSelection() != wxNOT_FOUND )
|
||||||
{
|
|
||||||
return m_libraryModels.at( m_modelNameCombobox->GetSelection() );
|
return m_libraryModels.at( m_modelNameCombobox->GetSelection() );
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return m_models.at( static_cast<int>( m_curModelType ) );
|
return m_models.at( static_cast<int>( m_curModelType ) );
|
||||||
}
|
}
|
||||||
|
@ -803,6 +881,27 @@ void DIALOG_SIM_MODEL<T>::onBrowseButtonClick( wxCommandEvent& aEvent )
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DIALOG_SIM_MODEL<T>::onModelNameCombobox( wxCommandEvent& aEvent )
|
void DIALOG_SIM_MODEL<T>::onModelNameCombobox( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
|
if( IsIbisLoaded() )
|
||||||
|
{
|
||||||
|
wxArrayString pinLabels;
|
||||||
|
SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
|
||||||
|
|
||||||
|
if( !modelkibis )
|
||||||
|
{
|
||||||
|
wxFAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( std::pair<wxString, wxString> strs : modelkibis->GetIbisPins() )
|
||||||
|
{
|
||||||
|
pinLabels.Add( strs.first + " - " + strs.second );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ibisPinCombobox->Set( pinLabels );
|
||||||
|
|
||||||
|
wxArrayString emptyArray;
|
||||||
|
m_ibisModelCombobox->Set( emptyArray );
|
||||||
|
}
|
||||||
updateWidgets();
|
updateWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,10 +920,64 @@ void DIALOG_SIM_MODEL<T>::onModelNameComboboxTextEnter( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_modelNameCombobox->SetSelection(
|
m_modelNameCombobox->SetSelection(
|
||||||
m_modelNameCombobox->FindString( m_modelNameCombobox->GetValue() ) );
|
m_modelNameCombobox->FindString( m_modelNameCombobox->GetValue() ) );
|
||||||
|
onModelNameCombobox( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DIALOG_SIM_MODEL<T>::onIbisPinCombobox( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( IsIbisLoaded() )
|
||||||
|
{
|
||||||
|
wxArrayString modelLabels;
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
|
||||||
|
|
||||||
|
if( !modelkibis )
|
||||||
|
{
|
||||||
|
wxFAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> strs = modelkibis->GetIbisPins();
|
||||||
|
modelkibis->ChangePin( *std::dynamic_pointer_cast<SIM_LIBRARY_KIBIS>( m_library ),
|
||||||
|
strs.at( m_ibisPinCombobox->GetSelection() ).first );
|
||||||
|
|
||||||
|
for( wxString modelName : modelkibis->GetIbisModels() )
|
||||||
|
modelLabels.Add( modelName );
|
||||||
|
|
||||||
|
m_ibisModelCombobox->Set( modelLabels );
|
||||||
|
}
|
||||||
updateWidgets();
|
updateWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DIALOG_SIM_MODEL<T>::onIbisPinComboboxTextEnter( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_ibisPinCombobox->SetSelection(
|
||||||
|
m_ibisPinCombobox->FindString( m_ibisPinCombobox->GetValue() ) );
|
||||||
|
|
||||||
|
onIbisPinCombobox( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DIALOG_SIM_MODEL<T>::onIbisModelCombobox( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
updateWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DIALOG_SIM_MODEL<T>::onIbisModelComboboxTextEnter( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_ibisModelCombobox->SetSelection(
|
||||||
|
m_ibisModelCombobox->FindString( m_ibisModelCombobox->GetValue() ) );
|
||||||
|
|
||||||
|
onIbisPinCombobox( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DIALOG_SIM_MODEL<T>::onOverrideCheckbox( wxCommandEvent& aEvent )
|
void DIALOG_SIM_MODEL<T>::onOverrideCheckbox( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
|
@ -856,6 +1009,25 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
||||||
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
|
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
|
||||||
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
||||||
{
|
{
|
||||||
|
if( IsIbisLoaded()
|
||||||
|
&& ( type == SIM_MODEL::TYPE::KIBIS_DEVICE
|
||||||
|
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER ) )
|
||||||
|
{
|
||||||
|
std::shared_ptr<SIM_MODEL_KIBIS> kibismodel =
|
||||||
|
std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
|
||||||
|
m_libraryModels.at( m_modelNameCombobox->GetSelection() ) );
|
||||||
|
|
||||||
|
m_libraryModels.at( m_modelNameCombobox->GetSelection() ) =
|
||||||
|
std::shared_ptr<SIM_MODEL>( dynamic_cast<SIM_MODEL*>(
|
||||||
|
new SIM_MODEL_KIBIS( type, *kibismodel, m_fields ) ) );
|
||||||
|
|
||||||
|
wxCommandEvent dummyEvent;
|
||||||
|
onIbisPinCombobox( dummyEvent );
|
||||||
|
|
||||||
|
kibismodel = std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
|
||||||
|
m_libraryModels.at( m_modelNameCombobox->GetSelection() ) );
|
||||||
|
}
|
||||||
|
|
||||||
m_curModelType = type;
|
m_curModelType = type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -869,6 +1041,25 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DIALOG_SIM_MODEL<T>::onParamGridChanged( wxPropertyGridEvent& aEvent )
|
void DIALOG_SIM_MODEL<T>::onParamGridChanged( wxPropertyGridEvent& aEvent )
|
||||||
{
|
{
|
||||||
|
if( IsIbisLoaded() )
|
||||||
|
{
|
||||||
|
wxString propValue = "";
|
||||||
|
wxString propName = aEvent.GetPropertyName();
|
||||||
|
wxPGProperty* property = aEvent.GetProperty();
|
||||||
|
|
||||||
|
if( property && propName == "wftype" )
|
||||||
|
{
|
||||||
|
wxVariant variant = aEvent.GetPropertyValue();
|
||||||
|
propValue = property->ValueToString( variant );
|
||||||
|
|
||||||
|
std::shared_ptr<SIM_MODEL_KIBIS> kibismodel =
|
||||||
|
std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
|
||||||
|
m_libraryModels.at( m_modelNameCombobox->GetSelection() ) );
|
||||||
|
|
||||||
|
kibismodel->SetParameters( std::string( propValue.c_str() ) );
|
||||||
|
kibismodel->SetParamValue( "wftype", std::string( propValue.c_str() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
updateWidgets();
|
updateWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,7 +1156,7 @@ void DIALOG_SIM_MODEL<T>::onDeviceTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DIALOG_SIM_MODEL<T>::onTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
|
void DIALOG_SIM_MODEL<T>::onTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
|
||||||
{
|
{
|
||||||
aEvent.Enable( m_useInstanceModelRadioButton->GetValue() );
|
aEvent.Enable( m_useInstanceModelRadioButton->GetValue() || ( IsIbisLoaded() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1060,6 +1251,20 @@ void DIALOG_SIM_MODEL<T>::onParamGridSelectionChange( wxPropertyGridEvent& aEven
|
||||||
m_prevParamGridSelection = grid->GetSelection();
|
m_prevParamGridSelection = grid->GetSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DIALOG_SIM_MODEL<T>::setIbisMode( bool aIbisMode )
|
||||||
|
{
|
||||||
|
m_ibisModelCombobox->Show( aIbisMode );
|
||||||
|
m_ibisPinCombobox->Show( aIbisMode );
|
||||||
|
m_ibisModelLabel->Show( aIbisMode );
|
||||||
|
m_ibisPinLabel->Show( aIbisMode );
|
||||||
|
m_overrideCheckbox->Show( !aIbisMode );
|
||||||
|
|
||||||
|
m_modelNameLabel->SetLabel( aIbisMode ? "Component:" : "Model:" );
|
||||||
|
this->Fit();
|
||||||
|
this->Refresh();
|
||||||
|
this->Update();
|
||||||
|
}
|
||||||
|
|
||||||
template class DIALOG_SIM_MODEL<SCH_FIELD>;
|
template class DIALOG_SIM_MODEL<SCH_FIELD>;
|
||||||
template class DIALOG_SIM_MODEL<LIB_FIELD>;
|
template class DIALOG_SIM_MODEL<LIB_FIELD>;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <sim/sim_model.h>
|
#include <sim/sim_model.h>
|
||||||
#include <sim/sim_library.h>
|
#include <sim/sim_library.h>
|
||||||
#include <sch_symbol.h>
|
#include <sch_symbol.h>
|
||||||
|
#include <../../pcbnew/ibis/kibis.h>
|
||||||
|
|
||||||
|
|
||||||
// Some probable wxWidgets bugs encountered when writing this class:
|
// Some probable wxWidgets bugs encountered when writing this class:
|
||||||
|
@ -100,6 +101,10 @@ private:
|
||||||
void onModelNameCombobox( wxCommandEvent& aEvent ) override;
|
void onModelNameCombobox( wxCommandEvent& aEvent ) override;
|
||||||
void onModelNameComboboxKillFocus( wxFocusEvent& event ) override;
|
void onModelNameComboboxKillFocus( wxFocusEvent& event ) override;
|
||||||
void onModelNameComboboxTextEnter( wxCommandEvent& event ) override;
|
void onModelNameComboboxTextEnter( wxCommandEvent& event ) override;
|
||||||
|
void onIbisPinCombobox( wxCommandEvent& event ) override;
|
||||||
|
void onIbisPinComboboxTextEnter( wxCommandEvent& event ) override;
|
||||||
|
void onIbisModelCombobox( wxCommandEvent& event ) override;
|
||||||
|
void onIbisModelComboboxTextEnter( wxCommandEvent& event ) override;
|
||||||
void onOverrideCheckbox( wxCommandEvent& aEvent ) override;
|
void onOverrideCheckbox( wxCommandEvent& aEvent ) override;
|
||||||
void onDeviceTypeChoice( wxCommandEvent& aEvent ) override;
|
void onDeviceTypeChoice( wxCommandEvent& aEvent ) override;
|
||||||
void onTypeChoice( wxCommandEvent& aEvent ) override;
|
void onTypeChoice( wxCommandEvent& aEvent ) override;
|
||||||
|
@ -138,6 +143,11 @@ private:
|
||||||
|
|
||||||
wxPGProperty* m_prevParamGridSelection;
|
wxPGProperty* m_prevParamGridSelection;
|
||||||
bool m_wasCodePreviewUpdated;
|
bool m_wasCodePreviewUpdated;
|
||||||
|
|
||||||
|
std::shared_ptr<SIM_MODEL> m_currentIbisModel = nullptr;
|
||||||
|
|
||||||
|
void setIbisMode( bool aIbisMode );
|
||||||
|
bool IsIbisLoaded() { return m_library->GetType() == SIM_LIBRARY::LIBRARY_TYPE::KIBIS; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DIALOG_SIM_MODEL_H */
|
#endif /* DIALOG_SIM_MODEL_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
// C++ code generated with wxFormBuilder (version 3.10.1-88b0f50)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
@ -52,13 +52,36 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
||||||
fgSizer15->Add( m_modelNameLabel, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
fgSizer15->Add( m_modelNameLabel, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||||
|
|
||||||
m_modelNameCombobox = new wxComboBox( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
|
m_modelNameCombobox = new wxComboBox( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
|
||||||
fgSizer15->Add( m_modelNameCombobox, 0, wxALL|wxEXPAND, 5 );
|
fgSizer15->Add( m_modelNameCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
m_overrideCheckbox = new wxCheckBox( sbSizer4->GetStaticBox(), wxID_ANY, _("Override"), wxDefaultPosition, wxDefaultSize, 0 );
|
m_overrideCheckbox = new wxCheckBox( sbSizer4->GetStaticBox(), wxID_ANY, _("Override"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
fgSizer15->Add( m_overrideCheckbox, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
fgSizer15->Add( m_overrideCheckbox, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
sbSizer4->Add( fgSizer15, 1, wxEXPAND, 5 );
|
fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_ibisPinLabel = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Pin:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
|
||||||
|
m_ibisPinLabel->Wrap( -1 );
|
||||||
|
fgSizer15->Add( m_ibisPinLabel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxTOP, 5 );
|
||||||
|
|
||||||
|
m_ibisPinCombobox = new wxComboBox( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
|
||||||
|
fgSizer15->Add( m_ibisPinCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_ibisModelLabel = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Model:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
|
||||||
|
m_ibisModelLabel->Wrap( -1 );
|
||||||
|
fgSizer15->Add( m_ibisModelLabel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxTOP, 5 );
|
||||||
|
|
||||||
|
m_ibisModelCombobox = new wxComboBox( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
|
||||||
|
fgSizer15->Add( m_ibisModelCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
sbSizer4->Add( fgSizer15, 0, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
bSizer9->Add( sbSizer4, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 );
|
bSizer9->Add( sbSizer4, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 );
|
||||||
|
@ -243,6 +266,14 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
||||||
m_modelNameCombobox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
m_modelNameCombobox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
||||||
m_overrideCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckbox ), NULL, this );
|
m_overrideCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckbox ), NULL, this );
|
||||||
m_overrideCheckbox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckboxUpdate ), NULL, this );
|
m_overrideCheckbox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckboxUpdate ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisPinCombobox ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxKillFocus ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisPinComboboxTextEnter ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisModelCombobox ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxKillFocus ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisModelComboboxTextEnter ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
||||||
m_deviceTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
|
m_deviceTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
|
||||||
m_deviceTypeChoice->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoiceUpdate ), NULL, this );
|
m_deviceTypeChoice->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoiceUpdate ), NULL, this );
|
||||||
m_typeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onTypeChoice ), NULL, this );
|
m_typeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onTypeChoice ), NULL, this );
|
||||||
|
@ -268,6 +299,14 @@ DIALOG_SIM_MODEL_BASE::~DIALOG_SIM_MODEL_BASE()
|
||||||
m_modelNameCombobox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
m_modelNameCombobox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
||||||
m_overrideCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckbox ), NULL, this );
|
m_overrideCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckbox ), NULL, this );
|
||||||
m_overrideCheckbox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckboxUpdate ), NULL, this );
|
m_overrideCheckbox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckboxUpdate ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Disconnect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisPinCombobox ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxKillFocus ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisPinComboboxTextEnter ), NULL, this );
|
||||||
|
m_ibisPinCombobox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Disconnect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisModelCombobox ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxKillFocus ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onIbisModelComboboxTextEnter ), NULL, this );
|
||||||
|
m_ibisModelCombobox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
|
||||||
m_deviceTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
|
m_deviceTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
|
||||||
m_deviceTypeChoice->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoiceUpdate ), NULL, this );
|
m_deviceTypeChoice->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onDeviceTypeChoiceUpdate ), NULL, this );
|
||||||
m_typeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onTypeChoice ), NULL, this );
|
m_typeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onTypeChoice ), NULL, this );
|
||||||
|
|
|
@ -193,7 +193,7 @@
|
||||||
<object class="sizeritem" expanded="1">
|
<object class="sizeritem" expanded="1">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND</property>
|
<property name="flag">wxEXPAND</property>
|
||||||
<property name="proportion">1</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxFlexGridSizer" expanded="1">
|
<object class="wxFlexGridSizer" expanded="1">
|
||||||
<property name="cols">4</property>
|
<property name="cols">4</property>
|
||||||
<property name="flexible_direction">wxBOTH</property>
|
<property name="flexible_direction">wxBOTH</property>
|
||||||
|
@ -549,7 +549,7 @@
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="1">
|
<object class="sizeritem" expanded="1">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxALL|wxEXPAND</property>
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxComboBox" expanded="1">
|
<object class="wxComboBox" expanded="1">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
|
@ -682,6 +682,296 @@
|
||||||
<event name="OnUpdateUI">onOverrideCheckboxUpdate</event>
|
<event name="OnUpdateUI">onOverrideCheckboxUpdate</event>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="spacer" expanded="1">
|
||||||
|
<property name="height">0</property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="width">0</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxTOP</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxStaticText" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Pin:</property>
|
||||||
|
<property name="markup">0</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_ibisPinLabel</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style">wxALIGN_RIGHT</property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<property name="wrap">-1</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxComboBox" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="choices"></property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_ibisPinCombobox</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="selection">-1</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style">wxTE_PROCESS_ENTER</property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="value"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<event name="OnCombobox">onIbisPinCombobox</event>
|
||||||
|
<event name="OnKillFocus">onModelNameComboboxKillFocus</event>
|
||||||
|
<event name="OnTextEnter">onIbisPinComboboxTextEnter</event>
|
||||||
|
<event name="OnUpdateUI">onModelNameComboboxUpdate</event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="spacer" expanded="1">
|
||||||
|
<property name="height">0</property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="width">0</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxEXPAND</property>
|
||||||
|
<property name="proportion">1</property>
|
||||||
|
<object class="spacer" expanded="1">
|
||||||
|
<property name="height">0</property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="width">0</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxTOP</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxStaticText" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="label">Model:</property>
|
||||||
|
<property name="markup">0</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_ibisModelLabel</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style">wxALIGN_RIGHT</property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<property name="wrap">-1</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="1">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxComboBox" expanded="1">
|
||||||
|
<property name="BottomDockable">1</property>
|
||||||
|
<property name="LeftDockable">1</property>
|
||||||
|
<property name="RightDockable">1</property>
|
||||||
|
<property name="TopDockable">1</property>
|
||||||
|
<property name="aui_layer"></property>
|
||||||
|
<property name="aui_name"></property>
|
||||||
|
<property name="aui_position"></property>
|
||||||
|
<property name="aui_row"></property>
|
||||||
|
<property name="best_size"></property>
|
||||||
|
<property name="bg"></property>
|
||||||
|
<property name="caption"></property>
|
||||||
|
<property name="caption_visible">1</property>
|
||||||
|
<property name="center_pane">0</property>
|
||||||
|
<property name="choices"></property>
|
||||||
|
<property name="close_button">1</property>
|
||||||
|
<property name="context_help"></property>
|
||||||
|
<property name="context_menu">1</property>
|
||||||
|
<property name="default_pane">0</property>
|
||||||
|
<property name="dock">Dock</property>
|
||||||
|
<property name="dock_fixed">0</property>
|
||||||
|
<property name="docking">Left</property>
|
||||||
|
<property name="enabled">1</property>
|
||||||
|
<property name="fg"></property>
|
||||||
|
<property name="floatable">1</property>
|
||||||
|
<property name="font"></property>
|
||||||
|
<property name="gripper">0</property>
|
||||||
|
<property name="hidden">0</property>
|
||||||
|
<property name="id">wxID_ANY</property>
|
||||||
|
<property name="max_size"></property>
|
||||||
|
<property name="maximize_button">0</property>
|
||||||
|
<property name="maximum_size"></property>
|
||||||
|
<property name="min_size"></property>
|
||||||
|
<property name="minimize_button">0</property>
|
||||||
|
<property name="minimum_size"></property>
|
||||||
|
<property name="moveable">1</property>
|
||||||
|
<property name="name">m_ibisModelCombobox</property>
|
||||||
|
<property name="pane_border">1</property>
|
||||||
|
<property name="pane_position"></property>
|
||||||
|
<property name="pane_size"></property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="pin_button">1</property>
|
||||||
|
<property name="pos"></property>
|
||||||
|
<property name="resize">Resizable</property>
|
||||||
|
<property name="selection">-1</property>
|
||||||
|
<property name="show">1</property>
|
||||||
|
<property name="size"></property>
|
||||||
|
<property name="style">wxTE_PROCESS_ENTER</property>
|
||||||
|
<property name="subclass">; ; forward_declare</property>
|
||||||
|
<property name="toolbar_pane">0</property>
|
||||||
|
<property name="tooltip"></property>
|
||||||
|
<property name="validator_data_type"></property>
|
||||||
|
<property name="validator_style">wxFILTER_NONE</property>
|
||||||
|
<property name="validator_type">wxDefaultValidator</property>
|
||||||
|
<property name="validator_variable"></property>
|
||||||
|
<property name="value"></property>
|
||||||
|
<property name="window_extra_style"></property>
|
||||||
|
<property name="window_name"></property>
|
||||||
|
<property name="window_style"></property>
|
||||||
|
<event name="OnCombobox">onIbisModelCombobox</event>
|
||||||
|
<event name="OnKillFocus">onModelNameComboboxKillFocus</event>
|
||||||
|
<event name="OnTextEnter">onIbisModelComboboxTextEnter</event>
|
||||||
|
<event name="OnUpdateUI">onModelNameComboboxUpdate</event>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
// C++ code generated with wxFormBuilder (version 3.10.1-88b0f50)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
@ -61,6 +61,10 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
|
||||||
wxStaticText* m_modelNameLabel;
|
wxStaticText* m_modelNameLabel;
|
||||||
wxComboBox* m_modelNameCombobox;
|
wxComboBox* m_modelNameCombobox;
|
||||||
wxCheckBox* m_overrideCheckbox;
|
wxCheckBox* m_overrideCheckbox;
|
||||||
|
wxStaticText* m_ibisPinLabel;
|
||||||
|
wxComboBox* m_ibisPinCombobox;
|
||||||
|
wxStaticText* m_ibisModelLabel;
|
||||||
|
wxComboBox* m_ibisModelCombobox;
|
||||||
wxNotebook* m_notebook4;
|
wxNotebook* m_notebook4;
|
||||||
wxPanel* m_parametersPanel;
|
wxPanel* m_parametersPanel;
|
||||||
wxStaticText* m_staticTextDevType;
|
wxStaticText* m_staticTextDevType;
|
||||||
|
@ -90,6 +94,10 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
|
||||||
virtual void onModelNameComboboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
virtual void onModelNameComboboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||||
virtual void onOverrideCheckbox( wxCommandEvent& event ) { event.Skip(); }
|
virtual void onOverrideCheckbox( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void onOverrideCheckboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
virtual void onOverrideCheckboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||||
|
virtual void onIbisPinCombobox( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void onIbisPinComboboxTextEnter( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void onIbisModelCombobox( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void onIbisModelComboboxTextEnter( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void onDeviceTypeChoice( wxCommandEvent& event ) { event.Skip(); }
|
virtual void onDeviceTypeChoice( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void onDeviceTypeChoiceUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
virtual void onDeviceTypeChoiceUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||||
virtual void onTypeChoice( wxCommandEvent& event ) { event.Skip(); }
|
virtual void onTypeChoice( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#include <env_paths.h>
|
#include <env_paths.h>
|
||||||
#include <sim/sim_library.h>
|
#include <sim/sim_library.h>
|
||||||
|
#include <sim/sim_library_kibis.h>
|
||||||
|
#include <sim/sim_model_kibis.h>
|
||||||
|
#include <sim/sim_model.h>
|
||||||
#include <sch_screen.h>
|
#include <sch_screen.h>
|
||||||
#include <sch_text.h>
|
#include <sch_text.h>
|
||||||
#include <sch_textbox.h>
|
#include <sch_textbox.h>
|
||||||
|
@ -39,8 +42,11 @@
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
#include <paths.h>
|
||||||
#include <pegtl.hpp>
|
#include <pegtl.hpp>
|
||||||
#include <pegtl/contrib/parse_tree.hpp>
|
#include <pegtl/contrib/parse_tree.hpp>
|
||||||
|
#include <../../pcbnew/ibis/kibis.h>
|
||||||
|
#include <wx/dir.h>
|
||||||
|
|
||||||
|
|
||||||
namespace NETLIST_EXPORTER_SPICE_PARSER
|
namespace NETLIST_EXPORTER_SPICE_PARSER
|
||||||
|
@ -122,6 +128,45 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
||||||
m_items.clear();
|
m_items.clear();
|
||||||
m_libParts.clear();
|
m_libParts.clear();
|
||||||
|
|
||||||
|
wxFileName cacheDir;
|
||||||
|
cacheDir.AssignDir( PATHS::GetUserCachePath() );
|
||||||
|
cacheDir.AppendDir( wxT( "ibis" ) );
|
||||||
|
|
||||||
|
if( !cacheDir.DirExists() )
|
||||||
|
{
|
||||||
|
cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||||
|
|
||||||
|
if( !cacheDir.DirExists() )
|
||||||
|
{
|
||||||
|
wxLogTrace(
|
||||||
|
"IBIS_CACHE:", wxT( "%s:%s:%d\n * failed to create ibis cache directory '%s'" ),
|
||||||
|
__FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDir dir;
|
||||||
|
wxString dirName = cacheDir.GetFullPath();
|
||||||
|
|
||||||
|
if( !dir.Open( dirName ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxFileName thisFile;
|
||||||
|
wxArrayString fileList;
|
||||||
|
wxString fileSpec = wxT( "*.cache" );
|
||||||
|
|
||||||
|
thisFile.SetPath( dirName ); // Set the base path to the cache folder
|
||||||
|
|
||||||
|
int numFilesFound = dir.GetAllFiles( dirName, &fileList, fileSpec );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < numFilesFound; i++ )
|
||||||
|
{
|
||||||
|
// Completes path to specific file so we can get its "last access" date
|
||||||
|
thisFile.SetFullName( fileList[i] );
|
||||||
|
wxRemoveFile( thisFile.GetFullPath() );
|
||||||
|
}
|
||||||
|
|
||||||
for( SCH_SHEET_PATH& sheet : GetSheets( aNetlistOptions ) )
|
for( SCH_SHEET_PATH& sheet : GetSheets( aNetlistOptions ) )
|
||||||
{
|
{
|
||||||
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
||||||
|
@ -135,6 +180,223 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
||||||
|
|
||||||
ITEM spiceItem;
|
ITEM spiceItem;
|
||||||
|
|
||||||
|
// @TODO This is to be removed once ngspice gets ibis support
|
||||||
|
if( SIM_MODEL::GetFieldValue( &( symbol->GetFields() ), SIM_MODEL::DEVICE_TYPE_FIELD )
|
||||||
|
== "IBIS" )
|
||||||
|
{
|
||||||
|
if( !readRefName( sheet, *symbol, spiceItem, refNames ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxString ibisFile = SIM_MODEL::GetFieldValue( &( symbol->GetFields() ),
|
||||||
|
SIM_LIBRARY::LIBRARY_FIELD );
|
||||||
|
wxString ibisModel = SIM_MODEL::GetFieldValue( &( symbol->GetFields() ),
|
||||||
|
SIM_LIBRARY_KIBIS::MODEL_FIELD );
|
||||||
|
wxString ibisPin = SIM_MODEL::GetFieldValue( &( symbol->GetFields() ),
|
||||||
|
SIM_LIBRARY_KIBIS::PIN_FIELD );
|
||||||
|
wxString ibisComp = SIM_MODEL::GetFieldValue( &( symbol->GetFields() ),
|
||||||
|
SIM_LIBRARY::NAME_FIELD );
|
||||||
|
wxString modelType =
|
||||||
|
SIM_MODEL::GetFieldValue( &( symbol->GetFields() ), SIM_MODEL::TYPE_FIELD );
|
||||||
|
|
||||||
|
wxString absolutePath = m_schematic->Prj().AbsolutePath( ibisFile );
|
||||||
|
|
||||||
|
KIBIS vkibis = KIBIS( std::string( absolutePath.c_str() ) );
|
||||||
|
|
||||||
|
if( !vkibis.m_valid )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Can't parse ibis file '%s'" ), ibisFile );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KIBIS_MODEL* kmodel = vkibis.GetModel( std::string( ibisModel.c_str() ) );
|
||||||
|
|
||||||
|
if( !kmodel )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Can't find model '%s'" ), ibisModel );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !kmodel->m_valid )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Invalid model '%s'" ), ibisModel );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KIBIS_COMPONENT* kcomp = vkibis.GetComponent( std::string( ibisComp.c_str() ) );
|
||||||
|
|
||||||
|
if( !kcomp )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Can't find model '%s'" ), ibisComp );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !kcomp->m_valid )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Invalid model '%s'" ), ibisComp );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KIBIS_PIN* kpin = kcomp->GetPin( std::string( ibisPin.c_str() ) );
|
||||||
|
|
||||||
|
if( !kpin )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Can't find model '%s'" ), ibisPin );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !kpin->m_valid )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Invalid model '%s'" ), ibisPin );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string modelData;
|
||||||
|
std::string modelName =
|
||||||
|
std::string( symbol->GetRef( &sheet ).c_str() ) + "_ibisGenerated";
|
||||||
|
|
||||||
|
spiceItem.libraryPath =
|
||||||
|
cacheDir.GetPath() + "/" + symbol->GetRef( &sheet ) + ".cache";
|
||||||
|
wxFile cacheFile( spiceItem.libraryPath, wxFile::write );
|
||||||
|
|
||||||
|
if( !cacheFile.IsOpened() )
|
||||||
|
{
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Cannot open file for writing: '%s'" ),
|
||||||
|
spiceItem.libraryPath );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spiceItem.model =
|
||||||
|
SIM_MODEL::Create( static_cast<unsigned>( m_sortedSymbolPinList.size() ),
|
||||||
|
symbol->GetFields() );
|
||||||
|
|
||||||
|
SIM_MODEL::TYPE type = spiceItem.model->GetType();
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case SIM_MODEL::TYPE::KIBIS_DEVICE:
|
||||||
|
case SIM_MODEL::TYPE::KIBIS_DRIVER: break;
|
||||||
|
default:
|
||||||
|
wxLogTrace( "IBIS:", wxT( "Invalid ibis type: '%s'" ),
|
||||||
|
symbol->GetRef( &sheet ) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m_libraries.try_emplace( spiceItem.libraryPath,
|
||||||
|
SIM_LIBRARY::Create( spiceItem.libraryPath ) );
|
||||||
|
|
||||||
|
readNameField( *symbol, spiceItem );
|
||||||
|
|
||||||
|
if( !readModel( *symbol, spiceItem ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
spiceItem.modelName = modelName;
|
||||||
|
|
||||||
|
readPinNumbers( *symbol, spiceItem );
|
||||||
|
readPinNetNames( *symbol, spiceItem, ncCounter );
|
||||||
|
|
||||||
|
|
||||||
|
KIBIS_PARAMETER kparams;
|
||||||
|
const SIM_MODEL::PARAM* mparam;
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "vcc" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
kparams.SetCornerFromString( kparams.m_supply, mparam->value->ToString() );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "rpin" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
kparams.SetCornerFromString( kparams.m_Rpin, mparam->value->ToString() );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "lpin" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
kparams.SetCornerFromString( kparams.m_Lpin, mparam->value->ToString() );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "cpin" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
kparams.SetCornerFromString( kparams.m_Cpin, mparam->value->ToString() );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "ccomp" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
kparams.SetCornerFromString( kparams.m_Ccomp, mparam->value->ToString() );
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case SIM_MODEL::TYPE::KIBIS_DEVICE:
|
||||||
|
kpin->writeSpiceDevice( &modelData, modelName, *kmodel, kparams );
|
||||||
|
break;
|
||||||
|
case SIM_MODEL::TYPE::KIBIS_DRIVER:
|
||||||
|
{
|
||||||
|
mparam = spiceItem.model->FindParam( "wftype" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
{
|
||||||
|
std::string paramValue = mparam->value->ToString();
|
||||||
|
|
||||||
|
if( paramValue == "rect" )
|
||||||
|
{
|
||||||
|
kparams.m_waveform = static_cast<KIBIS_WAVEFORM*>(
|
||||||
|
new KIBIS_WAVEFORM_RECTANGULAR() );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "ton" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( kparams.m_waveform )
|
||||||
|
->m_ton = static_cast<double>(
|
||||||
|
std::dynamic_pointer_cast<SIM_VALUE_FLOAT>( mparam->value )
|
||||||
|
->Get()
|
||||||
|
.value_or( 1 ) );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "toff" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( kparams.m_waveform )
|
||||||
|
->m_toff = static_cast<double>(
|
||||||
|
std::dynamic_pointer_cast<SIM_VALUE_FLOAT>( mparam->value )
|
||||||
|
->Get()
|
||||||
|
.value_or( 1 ) );
|
||||||
|
|
||||||
|
mparam = spiceItem.model->FindParam( "delay" );
|
||||||
|
|
||||||
|
if( mparam )
|
||||||
|
static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( kparams.m_waveform )
|
||||||
|
->m_delay = static_cast<double>(
|
||||||
|
std::dynamic_pointer_cast<SIM_VALUE_FLOAT>( mparam->value )
|
||||||
|
->Get()
|
||||||
|
.value_or( 0 ) );
|
||||||
|
}
|
||||||
|
else if( paramValue == "stuck high" )
|
||||||
|
{
|
||||||
|
kparams.m_waveform =
|
||||||
|
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH() );
|
||||||
|
}
|
||||||
|
else if( paramValue == "stuck low" )
|
||||||
|
{
|
||||||
|
kparams.m_waveform =
|
||||||
|
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_LOW() );
|
||||||
|
}
|
||||||
|
else if( paramValue == "high Z" )
|
||||||
|
{
|
||||||
|
kparams.m_waveform =
|
||||||
|
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kpin->writeSpiceDriver( &modelData, modelName, *kmodel, kparams );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheFile.Write( wxString( modelData ) );
|
||||||
|
|
||||||
|
m_items.push_back( std::move( spiceItem ) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if( !readRefName( sheet, *symbol, spiceItem, refNames ) )
|
if( !readRefName( sheet, *symbol, spiceItem, refNames ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,18 @@
|
||||||
|
|
||||||
#include <sim/sim_library.h>
|
#include <sim/sim_library.h>
|
||||||
#include <sim/sim_library_spice.h>
|
#include <sim/sim_library_spice.h>
|
||||||
|
#include <sim/sim_library_kibis.h>
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( std::string aFilePath )
|
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( std::string aFilePath )
|
||||||
{
|
{
|
||||||
std::unique_ptr<SIM_LIBRARY> library = std::make_unique<SIM_LIBRARY_SPICE>();
|
std::unique_ptr<SIM_LIBRARY> library;
|
||||||
|
wxString wxaFilePath( aFilePath );
|
||||||
|
|
||||||
|
if( wxaFilePath.EndsWith( ".ibs" ) )
|
||||||
|
library = std::make_unique<SIM_LIBRARY_KIBIS>();
|
||||||
|
else
|
||||||
|
library = std::make_unique<SIM_LIBRARY_SPICE>();
|
||||||
|
|
||||||
library->ReadFile( aFilePath );
|
library->ReadFile( aFilePath );
|
||||||
return library;
|
return library;
|
||||||
|
|
|
@ -70,7 +70,11 @@ public:
|
||||||
|
|
||||||
std::string GetFilePath() const { return m_filePath; }
|
std::string GetFilePath() const { return m_filePath; }
|
||||||
std::string GetError() const { return m_error; }
|
std::string GetError() const { return m_error; }
|
||||||
|
|
||||||
|
DEFINE_ENUM_CLASS_WITH_ITERATOR( LIBRARY_TYPE, NONE, KIBIS, SPICE )
|
||||||
|
|
||||||
|
virtual SIM_LIBRARY::LIBRARY_TYPE GetType() { return SIM_LIBRARY::LIBRARY_TYPE::NONE; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
||||||
std::vector<std::string> m_modelNames;
|
std::vector<std::string> m_modelNames;
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* 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 <sim/sim_library_kibis.h>
|
||||||
|
#include <sim/sim_model_kibis.h>
|
||||||
|
#include <sim/spice_grammar.h>
|
||||||
|
#include <ki_exception.h>
|
||||||
|
#include <locale_io.h>
|
||||||
|
#include <pegtl.hpp>
|
||||||
|
#include <pegtl/contrib/parse_tree.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
|
||||||
|
{
|
||||||
|
SIM_LIBRARY::ReadFile( aFilePath );
|
||||||
|
m_kibis = KIBIS( std::string( aFilePath.c_str() ) );
|
||||||
|
|
||||||
|
if( !m_kibis.m_valid )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( wxString::Format( "Invalid ibis file." ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
||||||
|
{
|
||||||
|
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, 2 ) );
|
||||||
|
m_modelNames.emplace_back( kcomp.m_name );
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
|
||||||
|
InitModel( *libcomp, kcomp.m_name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SIM_LIBRARY_KIBIS::InitModel( SIM_MODEL_KIBIS& aModel, wxString aCompName )
|
||||||
|
{
|
||||||
|
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
||||||
|
{
|
||||||
|
if( kcomp.m_name != aCompName )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
aModel.m_componentName = kcomp.m_name;
|
||||||
|
aModel.m_ibisPins.clear();
|
||||||
|
|
||||||
|
for( KIBIS_PIN& kpin : kcomp.m_pins )
|
||||||
|
{
|
||||||
|
aModel.m_ibisPins.emplace_back( kpin.m_pinNumber, kpin.m_signalName );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* 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_LIBRARY_KIBIS_H
|
||||||
|
#define SIM_LIBRARY_KIBIS_H
|
||||||
|
|
||||||
|
#include <sim/sim_library.h>
|
||||||
|
#include <sim/sim_model_kibis.h>
|
||||||
|
#include <../../pcbnew/ibis/kibis.h>
|
||||||
|
|
||||||
|
class SIM_LIBRARY_KIBIS : public SIM_LIBRARY
|
||||||
|
{
|
||||||
|
friend class SIM_MODEL_KIBIS;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr auto PIN_FIELD = "Ibis_Pin";
|
||||||
|
static constexpr auto MODEL_FIELD = "Ibis_Model";
|
||||||
|
|
||||||
|
// @copydoc SIM_LIBRARY::ReadFile()
|
||||||
|
void ReadFile( const std::string& aFilePath ) override;
|
||||||
|
|
||||||
|
// @copydoc SIM_LIBRARY::WriteFile()
|
||||||
|
void WriteFile( const std::string& aFilePath ) override{};
|
||||||
|
|
||||||
|
virtual SIM_LIBRARY::LIBRARY_TYPE GetType() override
|
||||||
|
{
|
||||||
|
return SIM_LIBRARY::LIBRARY_TYPE::KIBIS;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool InitModel( SIM_MODEL_KIBIS& aModel, wxString aCompName );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
KIBIS m_kibis;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SIM_LIBRARY_SPICE_H
|
|
@ -42,6 +42,11 @@ public:
|
||||||
// @copydoc SIM_LIBRARY::WriteFile()
|
// @copydoc SIM_LIBRARY::WriteFile()
|
||||||
void WriteFile( const std::string& aFilePath ) override;
|
void WriteFile( const std::string& aFilePath ) override;
|
||||||
|
|
||||||
|
virtual SIM_LIBRARY::LIBRARY_TYPE GetType() override
|
||||||
|
{
|
||||||
|
return SIM_LIBRARY::LIBRARY_TYPE::SPICE;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SPICE_LIBRARY_PARSER> m_spiceLibraryParser;
|
std::unique_ptr<SPICE_LIBRARY_PARSER> m_spiceLibraryParser;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <sim/sim_model_ideal.h>
|
#include <sim/sim_model_ideal.h>
|
||||||
#include <sim/sim_model_mutual_inductor.h>
|
#include <sim/sim_model_mutual_inductor.h>
|
||||||
#include <sim/sim_model_ngspice.h>
|
#include <sim/sim_model_ngspice.h>
|
||||||
|
#include <sim/sim_model_kibis.h>
|
||||||
#include <sim/sim_model_source.h>
|
#include <sim/sim_model_source.h>
|
||||||
#include <sim/sim_model_raw_spice.h>
|
#include <sim/sim_model_raw_spice.h>
|
||||||
#include <sim/sim_model_subckt.h>
|
#include <sim/sim_model_subckt.h>
|
||||||
|
@ -97,6 +98,8 @@ SIM_MODEL::DEVICE_INFO SIM_MODEL::DeviceTypeInfo( DEVICE_TYPE_ aDeviceType )
|
||||||
case DEVICE_TYPE_::V: return { "V", "Voltage Source" };
|
case DEVICE_TYPE_::V: return { "V", "Voltage Source" };
|
||||||
case DEVICE_TYPE_::I: return { "I", "Current Source" };
|
case DEVICE_TYPE_::I: return { "I", "Current Source" };
|
||||||
|
|
||||||
|
case DEVICE_TYPE_::KIBIS: return { "IBIS", "Ibis model" };
|
||||||
|
|
||||||
case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" };
|
case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" };
|
||||||
case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" };
|
case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" };
|
||||||
case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" };
|
case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" };
|
||||||
|
@ -226,6 +229,8 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||||
//case TYPE::I_RANDPOISSON: return { DEVICE_TYPE::I, "RANDPOISSON", "Random Poisson" };
|
//case TYPE::I_RANDPOISSON: return { DEVICE_TYPE::I, "RANDPOISSON", "Random Poisson" };
|
||||||
case TYPE::I_BEHAVIORAL: return { DEVICE_TYPE_::I, "=", "Behavioral" };
|
case TYPE::I_BEHAVIORAL: return { DEVICE_TYPE_::I, "=", "Behavioral" };
|
||||||
|
|
||||||
|
case TYPE::KIBIS_DRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDRIVER", "Driver" };
|
||||||
|
case TYPE::KIBIS_DEVICE: return { DEVICE_TYPE_::KIBIS, "IBISDEVICE", "Device" };
|
||||||
case TYPE::SUBCKT: return { DEVICE_TYPE_::SUBCKT, "", "" };
|
case TYPE::SUBCKT: return { DEVICE_TYPE_::SUBCKT, "", "" };
|
||||||
case TYPE::XSPICE: return { DEVICE_TYPE_::XSPICE, "", "" };
|
case TYPE::XSPICE: return { DEVICE_TYPE_::XSPICE, "", "" };
|
||||||
case TYPE::RAWSPICE: return { DEVICE_TYPE_::SPICE, "", "" };
|
case TYPE::RAWSPICE: return { DEVICE_TYPE_::SPICE, "", "" };
|
||||||
|
@ -358,6 +363,8 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||||
case TYPE::SUBCKT: return { "X" };
|
case TYPE::SUBCKT: return { "X" };
|
||||||
case TYPE::XSPICE: return { "A" };
|
case TYPE::XSPICE: return { "A" };
|
||||||
|
|
||||||
|
case TYPE::KIBIS_DEVICE: return { "X" };
|
||||||
|
case TYPE::KIBIS_DRIVER: return { "X" };
|
||||||
case TYPE::NONE:
|
case TYPE::NONE:
|
||||||
case TYPE::RAWSPICE:
|
case TYPE::RAWSPICE:
|
||||||
return {};
|
return {};
|
||||||
|
@ -940,6 +947,10 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType )
|
||||||
case TYPE::XSPICE:
|
case TYPE::XSPICE:
|
||||||
return std::make_unique<SIM_MODEL_XSPICE>( aType );
|
return std::make_unique<SIM_MODEL_XSPICE>( aType );
|
||||||
|
|
||||||
|
case TYPE::KIBIS_DRIVER:
|
||||||
|
case TYPE::KIBIS_DEVICE:
|
||||||
|
return std::make_unique<SIM_MODEL_KIBIS>( aType );
|
||||||
|
|
||||||
case TYPE::RAWSPICE:
|
case TYPE::RAWSPICE:
|
||||||
return std::make_unique<SIM_MODEL_RAW_SPICE>();
|
return std::make_unique<SIM_MODEL_RAW_SPICE>();
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,7 @@ class SIM_MODEL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class SPICE_GENERATOR;
|
friend class SPICE_GENERATOR;
|
||||||
|
friend class NETLIST_EXPORTER_SPICE;
|
||||||
|
|
||||||
struct PIN;
|
struct PIN;
|
||||||
struct PARAM;
|
struct PARAM;
|
||||||
|
@ -139,6 +140,8 @@ public:
|
||||||
V,
|
V,
|
||||||
I,
|
I,
|
||||||
|
|
||||||
|
KIBIS,
|
||||||
|
|
||||||
SUBCKT,
|
SUBCKT,
|
||||||
XSPICE,
|
XSPICE,
|
||||||
SPICE
|
SPICE
|
||||||
|
@ -293,6 +296,8 @@ public:
|
||||||
//I_RANDPOISSON,
|
//I_RANDPOISSON,
|
||||||
I_BEHAVIORAL,
|
I_BEHAVIORAL,
|
||||||
|
|
||||||
|
KIBIS_DRIVER,
|
||||||
|
KIBIS_DEVICE,
|
||||||
|
|
||||||
SUBCKT,
|
SUBCKT,
|
||||||
XSPICE,
|
XSPICE,
|
||||||
|
@ -351,6 +356,7 @@ public:
|
||||||
LIMITING_VALUES,
|
LIMITING_VALUES,
|
||||||
ADVANCED,
|
ADVANCED,
|
||||||
FLAGS,
|
FLAGS,
|
||||||
|
WAVEFORM,
|
||||||
INITIAL_CONDITIONS,
|
INITIAL_CONDITIONS,
|
||||||
SUPERFLUOUS
|
SUPERFLUOUS
|
||||||
};
|
};
|
||||||
|
@ -410,7 +416,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<SIM_VALUE> value;
|
std::shared_ptr<SIM_VALUE> value;
|
||||||
const INFO& info;
|
const INFO& info;
|
||||||
bool isOtherVariant = false; // Legacy.
|
bool isOtherVariant = false; // Legacy.
|
||||||
|
|
||||||
|
@ -537,6 +543,9 @@ public:
|
||||||
void SetIsEnabled( bool aIsEnabled ) { m_isEnabled = aIsEnabled; }
|
void SetIsEnabled( bool aIsEnabled ) { m_isEnabled = aIsEnabled; }
|
||||||
bool IsEnabled() const { return m_isEnabled; }
|
bool IsEnabled() const { return m_isEnabled; }
|
||||||
|
|
||||||
|
bool RequiresUIUpdate() { return m_requiresUIUpdate; };
|
||||||
|
void UIUpdated() { m_requiresUIUpdate = false; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
|
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
|
||||||
|
|
||||||
|
@ -560,6 +569,8 @@ protected:
|
||||||
void InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields,
|
void InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields,
|
||||||
bool aAllowOnlyFirstValue = false,
|
bool aAllowOnlyFirstValue = false,
|
||||||
bool aAllowParamValuePairs = true );
|
bool aAllowParamValuePairs = true );
|
||||||
|
std::vector<PARAM> m_params;
|
||||||
|
bool m_requiresUIUpdate = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
|
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
|
||||||
|
@ -592,7 +603,6 @@ private:
|
||||||
|
|
||||||
const TYPE m_type;
|
const TYPE m_type;
|
||||||
std::vector<PIN> m_pins;
|
std::vector<PIN> m_pins;
|
||||||
std::vector<PARAM> m_params;
|
|
||||||
bool m_isEnabled;
|
bool m_isEnabled;
|
||||||
bool m_isInferred;
|
bool m_isInferred;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,302 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* 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 <sim/sim_model_kibis.h>
|
||||||
|
#include <sim/sim_library_kibis.h>
|
||||||
|
#include <../../pcbnew/ibis/kibis.h>
|
||||||
|
#include <locale_io.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
std::string SPICE_GENERATOR_KIBIS::ModelLine( const std::string& aModelName ) const
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> SPICE_GENERATOR_KIBIS::GetInstanceParams() const
|
||||||
|
{
|
||||||
|
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> vec;
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string> SPICE_GENERATOR_KIBIS::CurrentNames( const std::string& aRefName ) const
|
||||||
|
{
|
||||||
|
std::vector<std::string> currentNames;
|
||||||
|
|
||||||
|
for( const SIM_MODEL::PIN& pin : GetPins() )
|
||||||
|
{
|
||||||
|
currentNames.push_back( fmt::format( "I({:s}:{:s})", ItemName( aRefName ), pin.name ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, std::string aWfType ) :
|
||||||
|
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR_KIBIS>( *this ) )
|
||||||
|
{
|
||||||
|
SetParameters( aType, aWfType );
|
||||||
|
|
||||||
|
AddPin( { "GND", "1" } );
|
||||||
|
AddPin( { "IN/OUT", "2" } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource ) : SIM_MODEL_KIBIS( aType )
|
||||||
|
{
|
||||||
|
for( PARAM& param1 : m_params )
|
||||||
|
{
|
||||||
|
for( auto param2refwrap : aSource.GetParams() )
|
||||||
|
{
|
||||||
|
const PARAM& param2 = param2refwrap.get();
|
||||||
|
|
||||||
|
if( param1.info.name == param2.info.name )
|
||||||
|
*( param1.value ) = *( param2.value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_componentName = aSource.m_componentName;
|
||||||
|
|
||||||
|
m_ibisPins = aSource.GetIbisPins();
|
||||||
|
m_ibisModels = aSource.GetIbisModels();
|
||||||
|
}
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource,
|
||||||
|
const std::vector<LIB_FIELD>& aFields ) :
|
||||||
|
SIM_MODEL_KIBIS( aType, aSource )
|
||||||
|
{
|
||||||
|
ReadDataFields( 2, &aFields );
|
||||||
|
}
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource,
|
||||||
|
const std::vector<SCH_FIELD>& aFields ) :
|
||||||
|
SIM_MODEL_KIBIS( aType, aSource )
|
||||||
|
{
|
||||||
|
ReadDataFields( 2, &aFields );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
|
||||||
|
{
|
||||||
|
static std::vector<PARAM::INFO> kibisparam_device =
|
||||||
|
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DEVICE, "Dummy" );
|
||||||
|
static std::vector<PARAM::INFO> kibisparam_driver_rect =
|
||||||
|
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_RECT );
|
||||||
|
static std::vector<PARAM::INFO> kibisparam_driver_stuckh =
|
||||||
|
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_STUCKH );
|
||||||
|
static std::vector<PARAM::INFO> kibisparam_driver_stuckl =
|
||||||
|
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_STUCKL );
|
||||||
|
static std::vector<PARAM::INFO> kibisparam_driver_highz =
|
||||||
|
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_HIGHZ );
|
||||||
|
static std::vector<PARAM::INFO> kibisparam_driver_allParams =
|
||||||
|
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, "NoInit" );
|
||||||
|
|
||||||
|
m_requiresUIUpdate = true;
|
||||||
|
|
||||||
|
static std::vector<PARAM::INFO>* params;
|
||||||
|
|
||||||
|
switch( aType )
|
||||||
|
{
|
||||||
|
case SIM_MODEL::TYPE::KIBIS_DEVICE: params = &kibisparam_device; break;
|
||||||
|
case SIM_MODEL::TYPE::KIBIS_DRIVER:
|
||||||
|
|
||||||
|
if( aWfType == SIM_MODEL_KIBIS::DRIVER_RECT )
|
||||||
|
params = &kibisparam_driver_rect;
|
||||||
|
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_STUCKH )
|
||||||
|
params = &kibisparam_driver_stuckh;
|
||||||
|
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_STUCKL )
|
||||||
|
params = &kibisparam_driver_stuckl;
|
||||||
|
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_HIGHZ )
|
||||||
|
params = &kibisparam_driver_highz;
|
||||||
|
else
|
||||||
|
params = &kibisparam_driver_allParams;
|
||||||
|
// All params allow for a newly created model to read any parameter
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: wxFAIL; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_params.empty() )
|
||||||
|
{
|
||||||
|
for( const PARAM::INFO& paramInfo : *params )
|
||||||
|
AddParam( paramInfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( PARAM& param : m_params )
|
||||||
|
{
|
||||||
|
// We don't erase other params because we don't want to reset their values
|
||||||
|
if( param.info.category == PARAM::CATEGORY::WAVEFORM )
|
||||||
|
{
|
||||||
|
m_params.pop_back(); // waveform parameters are at the end of the vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( const PARAM::INFO& paramInfo : *params )
|
||||||
|
{
|
||||||
|
if( paramInfo.category == PARAM::CATEGORY::WAVEFORM )
|
||||||
|
{
|
||||||
|
AddParam( paramInfo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIM_MODEL_KIBIS::SetParameters( std::string aWfType )
|
||||||
|
{
|
||||||
|
SetParameters( GetType(), aWfType );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIM_MODEL_KIBIS::CreatePins( unsigned aSymbolPinCount )
|
||||||
|
{
|
||||||
|
SIM_MODEL::CreatePins( aSymbolPinCount );
|
||||||
|
|
||||||
|
// Reset the pins to Not Connected. Linear order is not as common, and reordering the pins is
|
||||||
|
// more effort in the GUI than assigning them from scratch.
|
||||||
|
for( int pinIndex = 0; pinIndex < GetPinCount(); ++pinIndex )
|
||||||
|
SetPinSymbolPinNumber( pinIndex, "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<SIM_MODEL::PARAM::INFO>
|
||||||
|
SIM_MODEL_KIBIS::makeKibisParamInfos( TYPE aType, std::string aWfType )
|
||||||
|
{
|
||||||
|
std::vector<PARAM::INFO> paramInfos;
|
||||||
|
PARAM::INFO paramInfo;
|
||||||
|
|
||||||
|
paramInfo.name = "vcc";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||||
|
paramInfo.unit = "";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||||
|
paramInfo.defaultValue = "TYP";
|
||||||
|
paramInfo.description = _( "Power supply" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfo.enumValues = { "TYP", "MIN", "MAX" };
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
paramInfo.name = "rpin";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||||
|
paramInfo.unit = "";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||||
|
paramInfo.defaultValue = "TYP";
|
||||||
|
paramInfo.description = _( "Parasitic Resistance" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfo.enumValues = { "TYP", "MIN", "MAX" };
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
paramInfo.name = "lpin";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||||
|
paramInfo.unit = "";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||||
|
paramInfo.defaultValue = "TYP";
|
||||||
|
paramInfo.description = _( "Parasitic Pin Inductance" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfo.enumValues = { "TYP", "MIN", "MAX" };
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
paramInfo.name = "cpin";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||||
|
paramInfo.unit = "";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||||
|
paramInfo.defaultValue = "TYP";
|
||||||
|
paramInfo.description = _( "Parasitic Pin Capacitance" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfo.enumValues = { "TYP", "MIN", "MAX" };
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
if ( aType == SIM_MODEL::TYPE::KIBIS_DEVICE )
|
||||||
|
return paramInfos; // Devices have no waveform parameters
|
||||||
|
|
||||||
|
paramInfo.name = "ac";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||||
|
paramInfo.unit = "";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||||
|
paramInfo.defaultValue = "normal";
|
||||||
|
paramInfo.description = _( "Modeling accuracy" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfo.enumValues = { "low", "normal", "high" };
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
paramInfo.name = "wftype";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||||
|
paramInfo.unit = "";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||||
|
paramInfo.defaultValue = DRIVER_HIGHZ;
|
||||||
|
paramInfo.description = _( "Waveform" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfo.enumValues = { DRIVER_RECT, DRIVER_STUCKH, DRIVER_STUCKL, DRIVER_HIGHZ };
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
if( aWfType == DRIVER_STUCKH || aWfType == DRIVER_STUCKL || aWfType == DRIVER_HIGHZ )
|
||||||
|
{
|
||||||
|
return paramInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
paramInfo.name = "ton";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
|
||||||
|
paramInfo.unit = "s";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||||
|
paramInfo.defaultValue = "";
|
||||||
|
paramInfo.description = _( "ON time" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
paramInfo.name = "toff";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
|
||||||
|
paramInfo.unit = "s";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||||
|
paramInfo.defaultValue = "";
|
||||||
|
paramInfo.description = _( "OFF time" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
paramInfo.name = "delay";
|
||||||
|
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
|
||||||
|
paramInfo.unit = "s";
|
||||||
|
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||||
|
paramInfo.defaultValue = "0";
|
||||||
|
paramInfo.description = _( "Delay" );
|
||||||
|
paramInfo.spiceModelName = "";
|
||||||
|
paramInfos.push_back( paramInfo );
|
||||||
|
|
||||||
|
return paramInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SIM_MODEL_KIBIS::ChangePin( SIM_LIBRARY_KIBIS& aLib, std::string aPinNumber )
|
||||||
|
{
|
||||||
|
KIBIS_COMPONENT* kcomp = aLib.m_kibis.GetComponent( std::string( GetComponentName() ) );
|
||||||
|
|
||||||
|
if( !kcomp )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
KIBIS_PIN* kpin = kcomp->GetPin( std::string( aPinNumber.c_str() ) );
|
||||||
|
|
||||||
|
if( !kpin )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_ibisModels.clear();
|
||||||
|
|
||||||
|
for( KIBIS_MODEL* kmodel : kpin->m_models )
|
||||||
|
m_ibisModels.push_back( kmodel->m_name );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* 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_KIBIS_H
|
||||||
|
#define SIM_MODEL_KIBIS_H
|
||||||
|
|
||||||
|
#include <sim/sim_model.h>
|
||||||
|
#include <sim/spice_generator.h>
|
||||||
|
|
||||||
|
class SIM_LIBRARY_KIBIS;
|
||||||
|
|
||||||
|
|
||||||
|
class SPICE_GENERATOR_KIBIS : public SPICE_GENERATOR
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using SPICE_GENERATOR::SPICE_GENERATOR;
|
||||||
|
|
||||||
|
std::string ModelLine( const std::string& aModelName ) const override;
|
||||||
|
std::vector<std::string> CurrentNames( const std::string& aRefName ) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SIM_MODEL_KIBIS : public SIM_MODEL
|
||||||
|
{
|
||||||
|
friend class SIM_LIBRARY_KIBIS;
|
||||||
|
|
||||||
|
static constexpr auto DRIVER_RECT = "rect";
|
||||||
|
static constexpr auto DRIVER_STUCKH = "stuck high";
|
||||||
|
static constexpr auto DRIVER_STUCKL = "stuck low";
|
||||||
|
static constexpr auto DRIVER_HIGHZ = "high Z";
|
||||||
|
|
||||||
|
public:
|
||||||
|
SIM_MODEL_KIBIS( TYPE aType, std::string aWfType = "NoInit" );
|
||||||
|
|
||||||
|
// @brief Special copy constructor
|
||||||
|
// creates a a model with aType, but tries to match parameters from aSource.
|
||||||
|
SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource );
|
||||||
|
|
||||||
|
SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector<LIB_FIELD>& aFields );
|
||||||
|
SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector<SCH_FIELD>& aFields );
|
||||||
|
|
||||||
|
void SetParameters( TYPE aType, std::string aWfType ); // To change between device / driver
|
||||||
|
void SetParameters( std::string aWfType ); // To change between device / driver
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> GetIbisPins() const
|
||||||
|
{
|
||||||
|
return GetBaseModel()
|
||||||
|
? dynamic_cast<const SIM_MODEL_KIBIS*>( GetBaseModel() )->GetIbisPins()
|
||||||
|
: m_ibisPins;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> GetIbisModels() const { return m_ibisModels; };
|
||||||
|
|
||||||
|
std::string GetComponentName() const
|
||||||
|
{
|
||||||
|
return GetBaseModel()
|
||||||
|
? dynamic_cast<const SIM_MODEL_KIBIS*>( GetBaseModel() )->GetComponentName()
|
||||||
|
: m_componentName;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief update the list of available models based on the pin number.
|
||||||
|
* */
|
||||||
|
bool ChangePin( SIM_LIBRARY_KIBIS& aLib, std::string aPinNumber );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void CreatePins( unsigned aSymbolPinCount ) override;
|
||||||
|
std::vector<std::pair<std::string, std::string>> m_ibisPins;
|
||||||
|
std::string m_componentName;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool requiresSpiceModelLine() const override { return true; }
|
||||||
|
static const std::vector<PARAM::INFO> makeKibisParamInfos( TYPE aType, std::string aWfType );
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos;
|
||||||
|
std::vector<std::string> m_ibisModels;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SIM_MODEL_KIBIS_H
|
|
@ -212,6 +212,8 @@ SIM_MODEL_NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() const
|
||||||
case TYPE::PMOS_HISIMHV1: return MODEL_TYPE::HISIMHV1;
|
case TYPE::PMOS_HISIMHV1: return MODEL_TYPE::HISIMHV1;
|
||||||
case TYPE::NMOS_HISIMHV2:
|
case TYPE::NMOS_HISIMHV2:
|
||||||
case TYPE::PMOS_HISIMHV2: return MODEL_TYPE::HISIMHV2;
|
case TYPE::PMOS_HISIMHV2: return MODEL_TYPE::HISIMHV2;
|
||||||
|
case TYPE::KIBIS_DRIVER:
|
||||||
|
case TYPE::KIBIS_DEVICE: return MODEL_TYPE::KIBIS;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_NGSPICE" );
|
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_NGSPICE" );
|
||||||
|
|
|
@ -87,7 +87,8 @@ protected:
|
||||||
B3SOIPD,
|
B3SOIPD,
|
||||||
HISIM2,
|
HISIM2,
|
||||||
HISIMHV1,
|
HISIMHV1,
|
||||||
HISIMHV2
|
HISIMHV2,
|
||||||
|
KIBIS
|
||||||
)
|
)
|
||||||
|
|
||||||
struct MODEL_INFO
|
struct MODEL_INFO
|
||||||
|
|
|
@ -120,6 +120,8 @@ public:
|
||||||
friend SIM_VALUE_INST<Type> operator/( const SIM_VALUE_INST<Type>& aLeft,
|
friend SIM_VALUE_INST<Type> operator/( const SIM_VALUE_INST<Type>& aLeft,
|
||||||
const SIM_VALUE_INST<Type>& aRight );
|
const SIM_VALUE_INST<Type>& aRight );
|
||||||
|
|
||||||
|
std::optional<T> Get() { return m_value; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getMetricSuffix();
|
std::string getMetricSuffix();
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ protected:
|
||||||
return m_model.GetPins();
|
return m_model.GetPins();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const;
|
virtual std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const;
|
||||||
|
|
||||||
const SIM_MODEL& m_model;
|
const SIM_MODEL& m_model;
|
||||||
};
|
};
|
||||||
|
|
|
@ -185,6 +185,8 @@ KIBIS_PIN::KIBIS_PIN( KIBIS* aTopLevel, IbisComponentPin& aPin, IbisComponentPac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KIBIS_MODEL::KIBIS_MODEL( KIBIS* aTopLevel, IbisModel& aSource, IbisParser& aParser ) :
|
KIBIS_MODEL::KIBIS_MODEL( KIBIS* aTopLevel, IbisModel& aSource, IbisParser& aParser ) :
|
||||||
|
@ -275,7 +277,7 @@ KIBIS_COMPONENT::KIBIS_COMPONENT( KIBIS* aTopLevel, IbisComponent& aSource, Ibis
|
||||||
m_valid = status;
|
m_valid = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
KIBIS_PIN* KIBIS_COMPONENT::getPin( std::string aPinNumber )
|
KIBIS_PIN* KIBIS_COMPONENT::GetPin( std::string aPinNumber )
|
||||||
{
|
{
|
||||||
for( KIBIS_PIN& pin : m_pins )
|
for( KIBIS_PIN& pin : m_pins )
|
||||||
{
|
{
|
||||||
|
@ -317,7 +319,7 @@ std::vector<std::pair<IbisWaveform*, IbisWaveform*>> KIBIS_MODEL::waveformPairs(
|
||||||
return pairs;
|
return pairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KIBIS_MODEL::SpiceDie( IBIS_CORNER aSupply, IBIS_CORNER aParasitics, int aIndex )
|
std::string KIBIS_MODEL::SpiceDie( KIBIS_PARAMETER& aParam, int aIndex )
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
|
@ -328,6 +330,9 @@ std::string KIBIS_MODEL::SpiceDie( IBIS_CORNER aSupply, IBIS_CORNER aParasitics,
|
||||||
std::string DIE = "DIE";
|
std::string DIE = "DIE";
|
||||||
std::string DIEBUFF = "DIEBUFF";
|
std::string DIEBUFF = "DIEBUFF";
|
||||||
|
|
||||||
|
IBIS_CORNER supply = aParam.m_supply;
|
||||||
|
IBIS_CORNER ccomp = aParam.m_Ccomp;
|
||||||
|
|
||||||
GC_GND += std::to_string( aIndex );
|
GC_GND += std::to_string( aIndex );
|
||||||
PC_PWR += std::to_string( aIndex );
|
PC_PWR += std::to_string( aIndex );
|
||||||
PU_PWR += std::to_string( aIndex );
|
PU_PWR += std::to_string( aIndex );
|
||||||
|
@ -348,34 +353,34 @@ std::string KIBIS_MODEL::SpiceDie( IBIS_CORNER aSupply, IBIS_CORNER aParasitics,
|
||||||
|
|
||||||
result = "\n";
|
result = "\n";
|
||||||
result += "VPWR POWER GND ";
|
result += "VPWR POWER GND ";
|
||||||
result += doubleToString( m_voltageRange.value[aSupply] );
|
result += doubleToString( m_voltageRange.value[supply] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "CCPOMP " + DIE + " GND ";
|
result += "CCPOMP " + DIE + " GND ";
|
||||||
result += doubleToString( m_C_comp.value[aParasitics] );
|
result += doubleToString( m_C_comp.value[ccomp] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
|
|
||||||
if( HasGNDClamp() )
|
if( HasGNDClamp() )
|
||||||
{
|
{
|
||||||
result += m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, aSupply );
|
result += m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, supply );
|
||||||
result += "VmeasGC GND " + GC_GND + " 0\n";
|
result += "VmeasGC GND " + GC_GND + " 0\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if( HasPOWERClamp() )
|
if( HasPOWERClamp() )
|
||||||
{
|
{
|
||||||
result += m_POWERClamp.Spice( aIndex * 4 + 2, "POWER", DIE, PC, aSupply );
|
result += m_POWERClamp.Spice( aIndex * 4 + 2, "POWER", DIE, PC, supply );
|
||||||
result += "VmeasPC POWER " + PC_PWR + " 0\n";
|
result += "VmeasPC POWER " + PC_PWR + " 0\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if( HasPulldown() )
|
if( HasPulldown() )
|
||||||
{
|
{
|
||||||
result += m_pulldown.Spice( aIndex * 4 + 3, DIEBUFF, PD_GND, PD, aSupply );
|
result += m_pulldown.Spice( aIndex * 4 + 3, DIEBUFF, PD_GND, PD, supply );
|
||||||
result += "VmeasPD GND " + PD_GND + " 0\n";
|
result += "VmeasPD GND " + PD_GND + " 0\n";
|
||||||
result += "BKD GND " + DIE + " i=( -i(VmeasPU) * v(KU) )\n";
|
result += "BKD GND " + DIE + " i=( -i(VmeasPU) * v(KU) )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if( HasPullup() )
|
if( HasPullup() )
|
||||||
{
|
{
|
||||||
result += m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIEBUFF, PU, aSupply );
|
result += m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIEBUFF, PU, supply );
|
||||||
result += "VmeasPU POWER " + PU_PWR + " 0\n";
|
result += "VmeasPU POWER " + PU_PWR + " 0\n";
|
||||||
result += "BKU POWER " + DIE + " i=( i(VmeasPD) * v(KD) )\n";
|
result += "BKU POWER " + DIE + " i=( i(VmeasPD) * v(KD) )\n";
|
||||||
}
|
}
|
||||||
|
@ -446,17 +451,18 @@ bool KIBIS_MODEL::HasPOWERClamp()
|
||||||
std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNode2,
|
std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNode2,
|
||||||
std::vector<std::pair<int, double>> aBits,
|
std::vector<std::pair<int, double>> aBits,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
||||||
IBIS_CORNER aSupply )
|
KIBIS_PARAMETER& aParam )
|
||||||
{
|
{
|
||||||
|
IBIS_CORNER supply = aParam.m_supply;
|
||||||
std::string simul;
|
std::string simul;
|
||||||
|
|
||||||
IbisWaveform risingWF = TrimWaveform( *( aPair.first ) );
|
IbisWaveform risingWF = TrimWaveform( *( aPair.first ) );
|
||||||
IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) );
|
IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) );
|
||||||
|
|
||||||
double deltaR = risingWF.m_table.m_entries.back().V.value[aSupply]
|
double deltaR = risingWF.m_table.m_entries.back().V.value[supply]
|
||||||
- risingWF.m_table.m_entries.at( 0 ).V.value[aSupply];
|
- risingWF.m_table.m_entries.at( 0 ).V.value[supply];
|
||||||
double deltaF = fallingWF.m_table.m_entries.back().V.value[aSupply]
|
double deltaF = fallingWF.m_table.m_entries.back().V.value[supply]
|
||||||
- fallingWF.m_table.m_entries.at( 0 ).V.value[aSupply];
|
- fallingWF.m_table.m_entries.at( 0 ).V.value[supply];
|
||||||
|
|
||||||
// Ideally, delta should be equal to zero.
|
// Ideally, delta should be equal to zero.
|
||||||
// It can be different from zero if the falling waveform does not start were the rising one ended.
|
// It can be different from zero if the falling waveform does not start were the rising one ended.
|
||||||
|
@ -498,7 +504,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
|
||||||
{
|
{
|
||||||
simul += doubleToString( entry.t + timing );
|
simul += doubleToString( entry.t + timing );
|
||||||
simul += " ";
|
simul += " ";
|
||||||
simul += doubleToString( entry.V.value[aSupply] - delta );
|
simul += doubleToString( entry.V.value[supply] - delta );
|
||||||
simul += " ";
|
simul += " ";
|
||||||
}
|
}
|
||||||
simul += ")\n";
|
simul += ")\n";
|
||||||
|
@ -521,21 +527,22 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
|
||||||
|
|
||||||
// Depending on the first bit, we add a different DC value
|
// Depending on the first bit, we add a different DC value
|
||||||
// The DC value we add is the first value of the first bit.
|
// The DC value we add is the first value of the first bit.
|
||||||
if( aBits[0].first == 0 )
|
if( ( aBits.size() > 0 ) && ( aBits[0].first == 0 ) )
|
||||||
{
|
{
|
||||||
simul += doubleToString( aPair.second->m_table.m_entries.at( 0 ).V.value[aSupply] );
|
simul += doubleToString( aPair.second->m_table.m_entries.at( 0 ).V.value[supply] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
simul += doubleToString( aPair.first->m_table.m_entries.at( 0 ).V.value[aSupply] );
|
simul += doubleToString( aPair.first->m_table.m_entries.at( 0 ).V.value[supply] );
|
||||||
}
|
}
|
||||||
|
|
||||||
simul += ")\n";
|
simul += ")\n";
|
||||||
return simul;
|
return simul;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KIBIS_PIN::addDie( KIBIS_MODEL& aModel, IBIS_CORNER aSupply, int aIndex )
|
std::string KIBIS_PIN::addDie( KIBIS_MODEL& aModel, KIBIS_PARAMETER& aParam, int aIndex )
|
||||||
{
|
{
|
||||||
|
IBIS_CORNER supply = aParam.m_supply;
|
||||||
std::string simul;
|
std::string simul;
|
||||||
|
|
||||||
std::string GC_GND = "GC_GND";
|
std::string GC_GND = "GC_GND";
|
||||||
|
@ -563,22 +570,22 @@ std::string KIBIS_PIN::addDie( KIBIS_MODEL& aModel, IBIS_CORNER aSupply, int aIn
|
||||||
|
|
||||||
if( aModel.HasGNDClamp() )
|
if( aModel.HasGNDClamp() )
|
||||||
{
|
{
|
||||||
simul += aModel.m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, aSupply );
|
simul += aModel.m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, supply );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aModel.HasPOWERClamp() )
|
if( aModel.HasPOWERClamp() )
|
||||||
{
|
{
|
||||||
simul += aModel.m_POWERClamp.Spice( aIndex * 4 + 2, PC_PWR, DIE, PC, aSupply );
|
simul += aModel.m_POWERClamp.Spice( aIndex * 4 + 2, PC_PWR, DIE, PC, supply );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aModel.HasPulldown() )
|
if( aModel.HasPulldown() )
|
||||||
{
|
{
|
||||||
simul += aModel.m_pulldown.Spice( aIndex * 4 + 3, DIE, PD_GND, PD, aSupply );
|
simul += aModel.m_pulldown.Spice( aIndex * 4 + 3, DIE, PD_GND, PD, supply );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aModel.HasPullup() )
|
if( aModel.HasPullup() )
|
||||||
{
|
{
|
||||||
simul += aModel.m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIE, PU, aSupply );
|
simul += aModel.m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIE, PU, supply );
|
||||||
}
|
}
|
||||||
|
|
||||||
return simul;
|
return simul;
|
||||||
|
@ -671,9 +678,12 @@ void KIBIS_PIN::getKuKdFromFile( std::string* aSimul )
|
||||||
|
|
||||||
std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aModel,
|
std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aModel,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
||||||
KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply, IBIS_CORNER aParasitics,
|
KIBIS_PARAMETER& aParam, int aIndex )
|
||||||
int aIndex )
|
|
||||||
{
|
{
|
||||||
|
IBIS_CORNER supply = aParam.m_supply;
|
||||||
|
IBIS_CORNER ccomp = aParam.m_Ccomp;
|
||||||
|
KIBIS_WAVEFORM* wave = aParam.m_waveform;
|
||||||
|
|
||||||
std::string simul = "";
|
std::string simul = "";
|
||||||
|
|
||||||
simul += "*THIS IS NOT A VALID SPICE MODEL.\n";
|
simul += "*THIS IS NOT A VALID SPICE MODEL.\n";
|
||||||
|
@ -690,6 +700,7 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
|
||||||
{
|
{
|
||||||
simul += "Vdummy 2 PIN 0\n";
|
simul += "Vdummy 2 PIN 0\n";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
simul += "RPIN 1 PIN ";
|
simul += "RPIN 1 PIN ";
|
||||||
|
@ -709,18 +720,23 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
|
||||||
|
|
||||||
simul += "\n";
|
simul += "\n";
|
||||||
simul += "CCPOMP 2 GND ";
|
simul += "CCPOMP 2 GND ";
|
||||||
simul += doubleToString( aModel.m_C_comp.value[aParasitics] ); //@TODO: Check the corner ?
|
simul += doubleToString( aModel.m_C_comp.value[ccomp] ); //@TODO: Check the corner ?
|
||||||
simul += "\n";
|
simul += "\n";
|
||||||
switch( aWave->GetType() )
|
|
||||||
|
IbisWaveform* risingWF = aPair.first;
|
||||||
|
IbisWaveform* fallingWF = aPair.second;
|
||||||
|
|
||||||
|
switch( wave->GetType() )
|
||||||
{
|
{
|
||||||
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
|
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
|
||||||
{
|
{
|
||||||
std::vector<std::pair<int, double>> bits;
|
std::vector<std::pair<int, double>> bits;
|
||||||
KIBIS_WAVEFORM_RECTANGULAR* rectWave = static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( aWave );
|
KIBIS_WAVEFORM_RECTANGULAR* rectWave = dynamic_cast<KIBIS_WAVEFORM_RECTANGULAR*>( wave );
|
||||||
|
|
||||||
IbisWaveform* risingWF = aPair.first;
|
|
||||||
IbisWaveform* fallingWF = aPair.second;
|
|
||||||
|
|
||||||
|
if( !rectWave )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
if( rectWave->m_ton < risingWF->m_table.m_entries.back().t )
|
if( rectWave->m_ton < risingWF->m_table.m_entries.back().t )
|
||||||
{
|
{
|
||||||
Report( _( "Rising edge is longer than on time." ), RPT_SEVERITY_WARNING );
|
Report( _( "Rising edge is longer than on time." ), RPT_SEVERITY_WARNING );
|
||||||
|
@ -744,22 +760,22 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
|
||||||
bits.push_back( bit );
|
bits.push_back( bit );
|
||||||
}
|
}
|
||||||
|
|
||||||
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aSupply );
|
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
|
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
|
||||||
{
|
{
|
||||||
IbisWaveform* fallingWF = aPair.second;
|
IbisWaveform* waveform = wave->inverted ? risingWF : fallingWF;
|
||||||
simul += "Vsig DIE0 GND ";
|
simul += "Vsig DIE0 GND ";
|
||||||
simul += doubleToString( fallingWF->m_table.m_entries.at( 0 ).V.value[aSupply] );
|
simul += doubleToString( waveform->m_table.m_entries.at( 0 ).V.value[supply] );
|
||||||
simul += "\n";
|
simul += "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
|
case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
|
||||||
{
|
{
|
||||||
IbisWaveform* risingWF = aPair.first;
|
IbisWaveform* waveform = wave->inverted ? fallingWF : risingWF;
|
||||||
simul += "Vsig DIE0 GND ";
|
simul += "Vsig DIE0 GND ";
|
||||||
simul += doubleToString( risingWF->m_table.m_entries.at( 0 ).V.value[aSupply] );
|
simul += doubleToString( waveform->m_table.m_entries.at( 0 ).V.value[supply] );
|
||||||
simul += "\n";
|
simul += "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -767,7 +783,7 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
|
||||||
case KIBIS_WAVEFORM_TYPE::HIGH_Z:
|
case KIBIS_WAVEFORM_TYPE::HIGH_Z:
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
simul += addDie( aModel, aSupply, 0 );
|
simul += addDie( aModel, aParam, 0 );
|
||||||
|
|
||||||
simul += "\n.ENDS DRIVER\n\n";
|
simul += "\n.ENDS DRIVER\n\n";
|
||||||
return simul;
|
return simul;
|
||||||
|
@ -775,11 +791,17 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
|
||||||
|
|
||||||
void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aModel,
|
void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aModel,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
||||||
KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply, IBIS_CORNER aParasitics )
|
KIBIS_PARAMETER& aParam )
|
||||||
{
|
{
|
||||||
|
IBIS_CORNER supply = aParam.m_supply;
|
||||||
|
KIBIS_WAVEFORM* wave = aParam.m_waveform;
|
||||||
|
|
||||||
std::string simul = "";
|
std::string simul = "";
|
||||||
|
|
||||||
if( aWave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
|
if( !wave )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( wave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
|
||||||
{
|
{
|
||||||
//@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
|
//@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
|
||||||
std::vector<double> ku, kd, t;
|
std::vector<double> ku, kd, t;
|
||||||
|
@ -792,11 +814,11 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
simul += KuKdDriver( aModel, aPair, aWave, aSupply, aParasitics, 0 );
|
simul += KuKdDriver( aModel, aPair, aParam, 0 );
|
||||||
simul += "\n x1 3 0 1 DRIVER0 \n";
|
simul += "\n x1 3 0 1 DRIVER0 \n";
|
||||||
|
|
||||||
simul += "VCC 3 0 ";
|
simul += "VCC 3 0 ";
|
||||||
simul += doubleToString( aModel.m_voltageRange.value[aSupply] );
|
simul += doubleToString( aModel.m_voltageRange.value[supply] );
|
||||||
simul += "\n";
|
simul += "\n";
|
||||||
//simul += "Vpin x1.DIE 0 1 \n"
|
//simul += "Vpin x1.DIE 0 1 \n"
|
||||||
simul += "Lfixture 1 4 ";
|
simul += "Lfixture 1 4 ";
|
||||||
|
@ -842,7 +864,7 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
|
||||||
Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
|
Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( aWave->GetType() )
|
switch( wave->GetType() )
|
||||||
{
|
{
|
||||||
case KIBIS_WAVEFORM_TYPE::RECTANGULAR: simul += ".tran 0.1n 1000n \n"; break;
|
case KIBIS_WAVEFORM_TYPE::RECTANGULAR: simul += ".tran 0.1n 1000n \n"; break;
|
||||||
|
|
||||||
|
@ -855,10 +877,10 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
|
||||||
simul += ".control run \n";
|
simul += ".control run \n";
|
||||||
simul += "set filetype=ascii\n";
|
simul += "set filetype=ascii\n";
|
||||||
simul += "run \n";
|
simul += "run \n";
|
||||||
simul += "plot v(x1.DIE0) i(VmeasIout) i(VmeasPD) i(VmeasPU) i(VmeasPC) i(VmeasGC)\n";
|
//simul += "plot v(x1.DIE0) i(VmeasIout) i(VmeasPD) i(VmeasPU) i(VmeasPC) i(VmeasGC)\n";
|
||||||
simul += "plot v(KU) v(KD)\n";
|
//simul += "plot v(KU) v(KD)\n";
|
||||||
simul += "write temp_output.spice v(KU) v(KD)\n"; // @TODO we might want to remove this...
|
simul += "write temp_output.spice v(KU) v(KD)\n"; // @TODO we might want to remove this...
|
||||||
//simul += "quit\n";
|
simul += "quit\n";
|
||||||
simul += ".endc \n";
|
simul += ".endc \n";
|
||||||
simul += ".end \n";
|
simul += ".end \n";
|
||||||
|
|
||||||
|
@ -866,15 +888,23 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KIBIS_PIN::getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply )
|
void KIBIS_PIN::getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_PARAMETER& aParam )
|
||||||
{
|
{
|
||||||
std::vector<double> ku, kd, t;
|
std::vector<double> ku, kd, t;
|
||||||
|
KIBIS_WAVEFORM* wave = aParam.m_waveform;
|
||||||
|
IBIS_CORNER& supply = aParam.m_supply;
|
||||||
|
|
||||||
switch( aWave->GetType() )
|
if( !wave )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( wave->GetType() )
|
||||||
{
|
{
|
||||||
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
|
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
|
||||||
{
|
{
|
||||||
KIBIS_WAVEFORM_RECTANGULAR* rectWave = static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( aWave );
|
KIBIS_WAVEFORM_RECTANGULAR* rectWave = static_cast<KIBIS_WAVEFORM_RECTANGULAR*>( wave );
|
||||||
|
|
||||||
for( int i = 0; i < rectWave->m_cycles; i++ )
|
for( int i = 0; i < rectWave->m_cycles; i++ )
|
||||||
{
|
{
|
||||||
ku.push_back( 0 );
|
ku.push_back( 0 );
|
||||||
|
@ -883,7 +913,7 @@ void KIBIS_PIN::getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_WAVEFORM* aWave, I
|
||||||
ku.push_back( 1 );
|
ku.push_back( 1 );
|
||||||
kd.push_back( 0 );
|
kd.push_back( 0 );
|
||||||
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i
|
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i
|
||||||
+ aModel.m_ramp.m_rising.value[aSupply].m_dt
|
+ aModel.m_ramp.m_rising.value[supply].m_dt
|
||||||
/ 0.6 ); // 0.6 because ibis only gives 20%-80% time
|
/ 0.6 ); // 0.6 because ibis only gives 20%-80% time
|
||||||
ku.push_back( 1 );
|
ku.push_back( 1 );
|
||||||
kd.push_back( 0 );
|
kd.push_back( 0 );
|
||||||
|
@ -891,21 +921,21 @@ void KIBIS_PIN::getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_WAVEFORM* aWave, I
|
||||||
ku.push_back( 0 );
|
ku.push_back( 0 );
|
||||||
kd.push_back( 1 );
|
kd.push_back( 1 );
|
||||||
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i + rectWave->m_toff
|
t.push_back( ( rectWave->m_ton + rectWave->m_toff ) * i + rectWave->m_toff
|
||||||
+ aModel.m_ramp.m_falling.value[aSupply].m_dt / 0.6 );
|
+ aModel.m_ramp.m_falling.value[supply].m_dt / 0.6 );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
|
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
|
||||||
{
|
{
|
||||||
ku.push_back( 1 );
|
ku.push_back( wave->inverted ? 0 : 1 );
|
||||||
kd.push_back( 0 );
|
kd.push_back( wave->inverted ? 1 : 0 );
|
||||||
t.push_back( 0 );
|
t.push_back( 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
|
case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
|
||||||
{
|
{
|
||||||
ku.push_back( 0 );
|
ku.push_back( wave->inverted ? 1 : 0 );
|
||||||
kd.push_back( 1 );
|
kd.push_back( wave->inverted ? 0 : 1 );
|
||||||
t.push_back( 0 );
|
t.push_back( 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -924,12 +954,16 @@ void KIBIS_PIN::getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_WAVEFORM* aWave, I
|
||||||
void KIBIS_PIN::getKuKdTwoWaveforms( KIBIS_MODEL& aModel,
|
void KIBIS_PIN::getKuKdTwoWaveforms( KIBIS_MODEL& aModel,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair1,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair1,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair2,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair2,
|
||||||
KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply,
|
KIBIS_PARAMETER& aParam )
|
||||||
IBIS_CORNER aParasitics )
|
|
||||||
{
|
{
|
||||||
std::string simul = "";
|
std::string simul = "";
|
||||||
|
IBIS_CORNER supply = aParam.m_supply;
|
||||||
|
KIBIS_WAVEFORM* wave = aParam.m_waveform;
|
||||||
|
|
||||||
if( aWave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
|
if( !wave )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( wave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
|
||||||
{
|
{
|
||||||
//@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
|
//@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
|
||||||
std::vector<double> ku, kd, t;
|
std::vector<double> ku, kd, t;
|
||||||
|
@ -942,12 +976,12 @@ void KIBIS_PIN::getKuKdTwoWaveforms( KIBIS_MODEL& aMo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
simul += KuKdDriver( aModel, aPair1, aWave, aSupply, aParasitics, 0 );
|
simul += KuKdDriver( aModel, aPair1, aParam, 0 );
|
||||||
simul += KuKdDriver( aModel, aPair2, aWave, aSupply, aParasitics, 1 );
|
simul += KuKdDriver( aModel, aPair2, aParam, 1 );
|
||||||
simul += "\n x1 3 0 1 DRIVER0 \n";
|
simul += "\n x1 3 0 1 DRIVER0 \n";
|
||||||
|
|
||||||
simul += "VCC 3 0 ";
|
simul += "VCC 3 0 ";
|
||||||
simul += doubleToString( aModel.m_voltageRange.value[aSupply] );
|
simul += doubleToString( aModel.m_voltageRange.value[supply] );
|
||||||
simul += "\n";
|
simul += "\n";
|
||||||
//simul += "Vpin x1.DIE 0 1 \n"
|
//simul += "Vpin x1.DIE 0 1 \n"
|
||||||
simul += "Lfixture0 1 4 ";
|
simul += "Lfixture0 1 4 ";
|
||||||
|
@ -1043,8 +1077,7 @@ void KIBIS_PIN::getKuKdTwoWaveforms( KIBIS_MODEL& aMo
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics, KIBIS_ACCURACY aAccuracy,
|
KIBIS_PARAMETER& aParam )
|
||||||
KIBIS_WAVEFORM* aWave )
|
|
||||||
{
|
{
|
||||||
bool status = true;
|
bool status = true;
|
||||||
|
|
||||||
|
@ -1091,38 +1124,39 @@ bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_M
|
||||||
result += "\n";
|
result += "\n";
|
||||||
|
|
||||||
result += "RPIN 1 PIN ";
|
result += "RPIN 1 PIN ";
|
||||||
result += doubleToString( m_Rpin.value[aParasitics] );
|
result += doubleToString( m_Rpin.value[aParam.m_Rpin] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "LPIN DIE0 1 ";
|
result += "LPIN DIE0 1 ";
|
||||||
result += doubleToString( m_Lpin.value[aParasitics] );
|
result += doubleToString( m_Lpin.value[aParam.m_Lpin] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "CPIN PIN GND ";
|
result += "CPIN PIN GND ";
|
||||||
result += doubleToString( m_Cpin.value[aParasitics] );
|
result += doubleToString( m_Cpin.value[aParam.m_Cpin] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
|
|
||||||
std::vector<std::pair<IbisWaveform*, IbisWaveform*>> wfPairs = aModel.waveformPairs();
|
std::vector<std::pair<IbisWaveform*, IbisWaveform*>> wfPairs = aModel.waveformPairs();
|
||||||
|
KIBIS_ACCURACY accuracy = aParam.m_accuracy;
|
||||||
|
|
||||||
if( wfPairs.size() < 1 || aAccuracy <= KIBIS_ACCURACY::LEVEL_0 )
|
if( wfPairs.size() < 1 || accuracy <= KIBIS_ACCURACY::LEVEL_0 )
|
||||||
{
|
{
|
||||||
if( aAccuracy > KIBIS_ACCURACY::LEVEL_0 )
|
if( accuracy > KIBIS_ACCURACY::LEVEL_0 )
|
||||||
{
|
{
|
||||||
Report( _( "Model has no waveform pair, using [Ramp] instead, poor accuracy" ),
|
Report( _( "Model has no waveform pair, using [Ramp] instead, poor accuracy" ),
|
||||||
RPT_SEVERITY_INFO );
|
RPT_SEVERITY_INFO );
|
||||||
}
|
}
|
||||||
getKuKdNoWaveform( aModel, aWave, aSupply );
|
getKuKdNoWaveform( aModel, aParam );
|
||||||
}
|
}
|
||||||
else if( wfPairs.size() == 1 || aAccuracy <= KIBIS_ACCURACY::LEVEL_1 )
|
else if( wfPairs.size() == 1 || accuracy <= KIBIS_ACCURACY::LEVEL_1 )
|
||||||
{
|
{
|
||||||
getKuKdOneWaveform( aModel, wfPairs.at( 0 ), aWave, aSupply, aParasitics );
|
getKuKdOneWaveform( aModel, wfPairs.at( 0 ), aParam );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( wfPairs.size() > 2 || aAccuracy <= KIBIS_ACCURACY::LEVEL_2 )
|
if( wfPairs.size() > 2 || accuracy <= KIBIS_ACCURACY::LEVEL_2 )
|
||||||
{
|
{
|
||||||
Report( _( "Model has more than 2 waveform pairs, using the first two." ),
|
Report( _( "Model has more than 2 waveform pairs, using the first two." ),
|
||||||
RPT_SEVERITY_WARNING );
|
RPT_SEVERITY_WARNING );
|
||||||
}
|
}
|
||||||
getKuKdTwoWaveforms( aModel, wfPairs.at( 0 ), wfPairs.at( 1 ), aWave, aSupply, aParasitics );
|
getKuKdTwoWaveforms( aModel, wfPairs.at( 0 ), wfPairs.at( 1 ), aParam );
|
||||||
}
|
}
|
||||||
|
|
||||||
result += "Vku KU GND pwl ( ";
|
result += "Vku KU GND pwl ( ";
|
||||||
|
@ -1147,7 +1181,7 @@ bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_M
|
||||||
|
|
||||||
result += ") \n";
|
result += ") \n";
|
||||||
|
|
||||||
result += aModel.SpiceDie( aSupply, aParasitics, 0 );
|
result += aModel.SpiceDie( aParam, 0 );
|
||||||
|
|
||||||
result += "\n.ENDS DRIVER\n\n";
|
result += "\n.ENDS DRIVER\n\n";
|
||||||
|
|
||||||
|
@ -1162,7 +1196,7 @@ bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_M
|
||||||
|
|
||||||
|
|
||||||
bool KIBIS_PIN::writeSpiceDevice( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
bool KIBIS_PIN::writeSpiceDevice( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics )
|
KIBIS_PARAMETER& aParam )
|
||||||
{
|
{
|
||||||
bool status = true;
|
bool status = true;
|
||||||
|
|
||||||
|
@ -1186,20 +1220,20 @@ bool KIBIS_PIN::writeSpiceDevice( std::string* aDest, std::string aName, KIBIS_M
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "RPIN 1 PIN ";
|
result += "RPIN 1 PIN ";
|
||||||
result += doubleToString( m_Rpin.value[aParasitics] );
|
result += doubleToString( m_Rpin.value[aParam.m_Rpin] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "LPIN DIE 1 ";
|
result += "LPIN DIE 1 ";
|
||||||
result += doubleToString( m_Lpin.value[aParasitics] );
|
result += doubleToString( m_Lpin.value[aParam.m_Lpin] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
result += "CPIN PIN GND ";
|
result += "CPIN PIN GND ";
|
||||||
result += doubleToString( m_Cpin.value[aParasitics] );
|
result += doubleToString( m_Cpin.value[aParam.m_Cpin] );
|
||||||
result += "\n";
|
result += "\n";
|
||||||
|
|
||||||
|
|
||||||
result += "Vku KU GND pwl ( 0 0 )\n";
|
result += "Vku KU GND pwl ( 0 0 )\n";
|
||||||
result += "Vkd KD GND pwl ( 0 0 )\n";
|
result += "Vkd KD GND pwl ( 0 0 )\n";
|
||||||
|
|
||||||
result += aModel.SpiceDie( aSupply, aParasitics, 0 );
|
result += aModel.SpiceDie( aParam, 0 );
|
||||||
|
|
||||||
result += "\n.ENDS DRIVER\n\n";
|
result += "\n.ENDS DRIVER\n\n";
|
||||||
|
|
||||||
|
@ -1213,10 +1247,13 @@ bool KIBIS_PIN::writeSpiceDevice( std::string* aDest, std::string aName, KIBIS_M
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KIBIS_PIN::writeSpiceDiffDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
bool KIBIS_PIN::writeSpiceDiffDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics,
|
KIBIS_PARAMETER& aParam )
|
||||||
KIBIS_ACCURACY aAccuracy, KIBIS_WAVEFORM* aWave )
|
|
||||||
{
|
{
|
||||||
bool status = true;
|
bool status = true;
|
||||||
|
KIBIS_WAVEFORM* wave = aParam.m_waveform;
|
||||||
|
|
||||||
|
if( !wave )
|
||||||
|
return false;
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
result = "\n*Differential driver model generated by Kicad using Ibis data. ";
|
result = "\n*Differential driver model generated by Kicad using Ibis data. ";
|
||||||
|
@ -1238,12 +1275,10 @@ bool KIBIS_PIN::writeSpiceDiffDriver( std::string* aDest, std::string aName, KIB
|
||||||
result += " GND PIN_P PIN_N\n";
|
result += " GND PIN_P PIN_N\n";
|
||||||
result += "\n";
|
result += "\n";
|
||||||
|
|
||||||
status &= writeSpiceDriver( &result, aName + "_P", aModel, aSupply, aParasitics, aAccuracy,
|
status &= writeSpiceDriver( &result, aName + "_P", aModel, aParam );
|
||||||
aWave );
|
wave->inverted = !wave->inverted;
|
||||||
aWave->inverted = !aWave->inverted;
|
status &= writeSpiceDriver( &result, aName + "_N", aModel, aParam );
|
||||||
status &= writeSpiceDriver( &result, aName + "_N", aModel, aSupply, aParasitics, aAccuracy,
|
wave->inverted = !wave->inverted;
|
||||||
aWave );
|
|
||||||
aWave->inverted = !aWave->inverted;
|
|
||||||
|
|
||||||
|
|
||||||
result += "\n";
|
result += "\n";
|
||||||
|
@ -1260,3 +1295,78 @@ bool KIBIS_PIN::writeSpiceDiffDriver( std::string* aDest, std::string aName, KIB
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KIBIS_PIN::writeSpiceDiffDevice( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
|
KIBIS_PARAMETER& aParam )
|
||||||
|
{
|
||||||
|
bool status = true;
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
result = "\n*Differential device model generated by Kicad using Ibis data. ";
|
||||||
|
result += "\n*Component: ";
|
||||||
|
|
||||||
|
if( m_parent )
|
||||||
|
{
|
||||||
|
result += m_parent->m_name;
|
||||||
|
}
|
||||||
|
result += "\n*Manufacturer: ";
|
||||||
|
|
||||||
|
if( m_parent )
|
||||||
|
{
|
||||||
|
result += m_parent->m_manufacturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "\n.SUBCKT ";
|
||||||
|
result += aName;
|
||||||
|
result += " GND PIN_P PIN_N\n";
|
||||||
|
result += "\n";
|
||||||
|
|
||||||
|
status &= writeSpiceDevice( &result, aName + "_P", aModel, aParam );
|
||||||
|
status &= writeSpiceDevice( &result, aName + "_N", aModel, aParam );
|
||||||
|
|
||||||
|
result += "\n";
|
||||||
|
result += "x1 GND PIN_P " + aName + "_P \n";
|
||||||
|
result += "x2 GND PIN_N " + aName + "_N \n";
|
||||||
|
result += "\n";
|
||||||
|
|
||||||
|
result += "\n.ENDS " + aName + "\n\n";
|
||||||
|
|
||||||
|
if( status )
|
||||||
|
{
|
||||||
|
*aDest += result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KIBIS_MODEL* KIBIS::GetModel( std::string aName )
|
||||||
|
{
|
||||||
|
for( KIBIS_MODEL& model : m_models )
|
||||||
|
{
|
||||||
|
if( model.m_name == aName )
|
||||||
|
return &model;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KIBIS_COMPONENT* KIBIS::GetComponent( std::string aName )
|
||||||
|
{
|
||||||
|
for( KIBIS_COMPONENT& cmp : m_components )
|
||||||
|
{
|
||||||
|
if( cmp.m_name == aName )
|
||||||
|
return &cmp;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, std::string aString )
|
||||||
|
{
|
||||||
|
if( aString == "MIN" )
|
||||||
|
aCorner = IBIS_CORNER::MIN;
|
||||||
|
else if( aString == "MAX" )
|
||||||
|
aCorner = IBIS_CORNER::MAX;
|
||||||
|
else
|
||||||
|
aCorner = IBIS_CORNER::TYP;
|
||||||
|
}
|
|
@ -64,6 +64,7 @@ public:
|
||||||
KIBIS_WAVEFORM(){};
|
KIBIS_WAVEFORM(){};
|
||||||
KIBIS_WAVEFORM_TYPE GetType() { return m_type; };
|
KIBIS_WAVEFORM_TYPE GetType() { return m_type; };
|
||||||
bool inverted = false; // Used for differential drivers
|
bool inverted = false; // Used for differential drivers
|
||||||
|
virtual ~KIBIS_WAVEFORM(){};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
KIBIS_WAVEFORM_TYPE m_type = KIBIS_WAVEFORM_TYPE::NONE;
|
KIBIS_WAVEFORM_TYPE m_type = KIBIS_WAVEFORM_TYPE::NONE;
|
||||||
|
@ -73,9 +74,9 @@ class KIBIS_WAVEFORM_RECTANGULAR : public KIBIS_WAVEFORM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KIBIS_WAVEFORM_RECTANGULAR() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR; };
|
KIBIS_WAVEFORM_RECTANGULAR() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR; };
|
||||||
double m_ton = 1;
|
double m_ton = 100e-9;
|
||||||
double m_toff = 1;
|
double m_toff = 100e-9;
|
||||||
int m_cycles = 1;
|
int m_cycles = 10;
|
||||||
double m_delay = 0;
|
double m_delay = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,6 +124,20 @@ enum class KIBIS_ACCURACY
|
||||||
LEVEL_3,
|
LEVEL_3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class KIBIS_PARAMETER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IBIS_CORNER m_Rpin = IBIS_CORNER::TYP;
|
||||||
|
IBIS_CORNER m_Lpin = IBIS_CORNER::TYP;
|
||||||
|
IBIS_CORNER m_Cpin = IBIS_CORNER::TYP;
|
||||||
|
IBIS_CORNER m_Ccomp = IBIS_CORNER::TYP;
|
||||||
|
IBIS_CORNER m_supply = IBIS_CORNER::TYP;
|
||||||
|
KIBIS_WAVEFORM* m_waveform;
|
||||||
|
KIBIS_ACCURACY m_accuracy = KIBIS_ACCURACY::LEVEL_2;
|
||||||
|
|
||||||
|
void SetCornerFromString( IBIS_CORNER& aCorner, std::string aString );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class KIBIS_FILE : KIBIS_ANY
|
class KIBIS_FILE : KIBIS_ANY
|
||||||
{
|
{
|
||||||
|
@ -145,10 +160,19 @@ public:
|
||||||
class KIBIS : public KIBIS_ANY
|
class KIBIS : public KIBIS_ANY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
KIBIS() : KIBIS_ANY( this ), m_file( this )
|
||||||
|
{
|
||||||
|
m_valid = false;
|
||||||
|
}; // Constructor for unitialized KIBIS members
|
||||||
KIBIS( std::string aFileName );
|
KIBIS( std::string aFileName );
|
||||||
std::vector<KIBIS_COMPONENT> m_components;
|
std::vector<KIBIS_COMPONENT> m_components;
|
||||||
std::vector<KIBIS_MODEL> m_models;
|
std::vector<KIBIS_MODEL> m_models;
|
||||||
KIBIS_FILE m_file;
|
KIBIS_FILE m_file;
|
||||||
|
|
||||||
|
/** @brief Return the model with name aName . Nullptr if not found */
|
||||||
|
KIBIS_MODEL* GetModel( std::string aName );
|
||||||
|
/** @brief Return the component with name aName . Nullptr if not found */
|
||||||
|
KIBIS_COMPONENT* GetComponent( std::string aName );
|
||||||
};
|
};
|
||||||
|
|
||||||
class KIBIS_MODEL : public KIBIS_ANY
|
class KIBIS_MODEL : public KIBIS_ANY
|
||||||
|
@ -201,12 +225,11 @@ public:
|
||||||
|
|
||||||
/** @brief Generate the spice directive to simulate the die
|
/** @brief Generate the spice directive to simulate the die
|
||||||
*
|
*
|
||||||
* @param aSupply Power supply corner
|
* @param aParam Parameters
|
||||||
* @param aParasitics Parasitics corner
|
|
||||||
* @param aIndex Index used to offset spice nodes / directives
|
* @param aIndex Index used to offset spice nodes / directives
|
||||||
* @return A multiline string with spice directives
|
* @return A multiline string with spice directives
|
||||||
*/
|
*/
|
||||||
std::string SpiceDie( IBIS_CORNER aSupply, IBIS_CORNER aParasitics, int aIndex );
|
std::string SpiceDie( KIBIS_PARAMETER& aParam, int aIndex );
|
||||||
|
|
||||||
/** @brief Create waveform pairs
|
/** @brief Create waveform pairs
|
||||||
*
|
*
|
||||||
|
@ -229,13 +252,13 @@ public:
|
||||||
* @param aBits The first member is the bit value ( 1 or 0 ).
|
* @param aBits The first member is the bit value ( 1 or 0 ).
|
||||||
* The second member is the time of the transition edge.
|
* The second member is the time of the transition edge.
|
||||||
* @param aPair @see waveformPairs()
|
* @param aPair @see waveformPairs()
|
||||||
* @param aSupply Power supply corner
|
* @param aParam Parameters
|
||||||
* @return A multiline string with spice directives
|
* @return A multiline string with spice directives
|
||||||
*/
|
*/
|
||||||
std::string generateSquareWave( std::string aNode1, std::string aNode2,
|
std::string generateSquareWave( std::string aNode1, std::string aNode2,
|
||||||
std::vector<std::pair<int, double>> aBits,
|
std::vector<std::pair<int, double>> aBits,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
||||||
IBIS_CORNER aSupply );
|
KIBIS_PARAMETER& aParam );
|
||||||
|
|
||||||
|
|
||||||
/** @brief Copy a waveform, and substract the first value to all samples
|
/** @brief Copy a waveform, and substract the first value to all samples
|
||||||
|
@ -275,30 +298,27 @@ public:
|
||||||
std::vector<KIBIS_MODEL*> m_models;
|
std::vector<KIBIS_MODEL*> m_models;
|
||||||
|
|
||||||
bool writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
bool writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics, KIBIS_ACCURACY aAccuracy,
|
KIBIS_PARAMETER& aParam );
|
||||||
KIBIS_WAVEFORM* aWave );
|
|
||||||
bool writeSpiceDiffDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
bool writeSpiceDiffDriver( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics,
|
KIBIS_PARAMETER& aParam );
|
||||||
KIBIS_ACCURACY aAccuracy, KIBIS_WAVEFORM* aWave );
|
|
||||||
bool writeSpiceDevice( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
bool writeSpiceDevice( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics );
|
KIBIS_PARAMETER& aParam );
|
||||||
|
bool writeSpiceDiffDevice( std::string* aDest, std::string aName, KIBIS_MODEL& aModel,
|
||||||
|
KIBIS_PARAMETER& aParam );
|
||||||
|
|
||||||
/** @brief Update m_Ku, m_Kd using no falling / rising waveform inputs ( low accuracy )
|
/** @brief Update m_Ku, m_Kd using no falling / rising waveform inputs ( low accuracy )
|
||||||
* @param aModel Model to be used
|
* @param aModel Model to be used
|
||||||
* @param aWave Waveform to generate
|
* @param aParam Parameters
|
||||||
* @param aSupply Power supply corner
|
|
||||||
*/
|
*/
|
||||||
void getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply );
|
void getKuKdNoWaveform( KIBIS_MODEL& aModel, KIBIS_PARAMETER& aParam );
|
||||||
|
|
||||||
/** @brief Update m_Ku, m_Kd using with a single waveform input
|
/** @brief Update m_Ku, m_Kd using with a single waveform input
|
||||||
* @param aModel Model to be used
|
* @param aModel Model to be used
|
||||||
* @param aPair @see waveformPairs()
|
* @param aPair @see waveformPairs()
|
||||||
* @param aWave Waveform to generate
|
* @param aParam Parameters
|
||||||
* @param aSupply Power supply corner
|
|
||||||
* @param aParasitics Parasitics corner
|
|
||||||
*/
|
*/
|
||||||
void getKuKdOneWaveform( KIBIS_MODEL& aModel, std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
void getKuKdOneWaveform( KIBIS_MODEL& aModel, std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
||||||
KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply, IBIS_CORNER aParasitics );
|
KIBIS_PARAMETER& aParam );
|
||||||
|
|
||||||
/** @brief Update m_Ku, m_Kd using with two waveform inputs
|
/** @brief Update m_Ku, m_Kd using with two waveform inputs
|
||||||
*
|
*
|
||||||
|
@ -306,29 +326,25 @@ public:
|
||||||
* @param aModel Model to be used
|
* @param aModel Model to be used
|
||||||
* @param aPair1 @see waveformPairs()
|
* @param aPair1 @see waveformPairs()
|
||||||
* @param aPair2 @see waveformPairs()
|
* @param aPair2 @see waveformPairs()
|
||||||
* @param aWave Waveform to generate
|
* @param aParam Parameters
|
||||||
* @param aSupply Power supply corner
|
* @param aIndex Index for numbering spice .SUBCKT
|
||||||
* @param aParasitics Parasitics corner
|
|
||||||
*/
|
*/
|
||||||
void getKuKdTwoWaveforms( KIBIS_MODEL& aModel, std::pair<IbisWaveform*, IbisWaveform*> aPair1,
|
void getKuKdTwoWaveforms( KIBIS_MODEL& aModel, std::pair<IbisWaveform*, IbisWaveform*> aPair1,
|
||||||
std::pair<IbisWaveform*, IbisWaveform*> aPair2, KIBIS_WAVEFORM* aWave,
|
std::pair<IbisWaveform*, IbisWaveform*> aPair2,
|
||||||
IBIS_CORNER aSupply, IBIS_CORNER aParasitics );
|
KIBIS_PARAMETER& aParam );
|
||||||
|
|
||||||
/** @brief Update m_Ku, m_Kd using with two waveform inputs
|
/** @brief Update m_Ku, m_Kd using with two waveform inputs
|
||||||
*
|
*
|
||||||
* The order of aPair1 and aPair2 is not important.
|
* The order of aPair1 and aPair2 is not important.
|
||||||
* @param aModel Model to be used
|
* @param aModel Model to be used
|
||||||
* @param aPair @see waveformPairs()
|
* @param aPair @see waveformPairs()
|
||||||
* @param aWave Waveform to generate
|
* @param aParam Parameters
|
||||||
* @param aSupply Power supply corner
|
|
||||||
* @param aParasitics Parasitics corner
|
|
||||||
* @param aIndex Index for numbering spice .SUBCKT
|
* @param aIndex Index for numbering spice .SUBCKT
|
||||||
*
|
*
|
||||||
* @return A multiline string with spice directives
|
* @return A multiline string with spice directives
|
||||||
*/
|
*/
|
||||||
std::string KuKdDriver( KIBIS_MODEL& aModel, std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
std::string KuKdDriver( KIBIS_MODEL& aModel, std::pair<IbisWaveform*, IbisWaveform*> aPair,
|
||||||
KIBIS_WAVEFORM* aWave, IBIS_CORNER aSupply, IBIS_CORNER aParasitics,
|
KIBIS_PARAMETER& aParam, int aIndex );
|
||||||
int aIndex );
|
|
||||||
|
|
||||||
/** @brief Generate the spice directive to simulate the die for Ku/Kd estimation
|
/** @brief Generate the spice directive to simulate the die for Ku/Kd estimation
|
||||||
*
|
*
|
||||||
|
@ -336,11 +352,11 @@ public:
|
||||||
* It sole purpose is to run the internal simulation to get Ku/Kd
|
* It sole purpose is to run the internal simulation to get Ku/Kd
|
||||||
*
|
*
|
||||||
* @param aModel Model to be used
|
* @param aModel Model to be used
|
||||||
* @param aSupply Power supply corner
|
* @param aParam Parameters
|
||||||
* @param aIndex Index for numbering ports
|
* @param aIndex Index for numbering ports
|
||||||
* @return A multiline string with spice directives
|
* @return A multiline string with spice directives
|
||||||
*/
|
*/
|
||||||
std::string addDie( KIBIS_MODEL& aModel, IBIS_CORNER aSupply, int aIndex );
|
std::string addDie( KIBIS_MODEL& aModel, KIBIS_PARAMETER& aParam, int aIndex );
|
||||||
|
|
||||||
|
|
||||||
/** @brief Update m_Ku, m_Kd using with two waveform inputs
|
/** @brief Update m_Ku, m_Kd using with two waveform inputs
|
||||||
|
@ -370,7 +386,7 @@ public:
|
||||||
* @param aPinNumber pin number
|
* @param aPinNumber pin number
|
||||||
* @return pointer to a KIBIS_PIN, or nullptr if there is no matching pin
|
* @return pointer to a KIBIS_PIN, or nullptr if there is no matching pin
|
||||||
*/
|
*/
|
||||||
KIBIS_PIN* getPin( std::string aPinNumber );
|
KIBIS_PIN* GetPin( std::string aPinNumber );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,10 +18,8 @@ int main( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//KIBIS_PIN* pin1 = comp.getPin( "11" );
|
KIBIS_PIN* pin1 = comp.GetPin( "30" );
|
||||||
//KIBIS_PIN* pin2 = comp.getPin( "2" );
|
KIBIS_PIN* pin2 = comp.GetPin( "31" );
|
||||||
KIBIS_PIN* pin1 = comp.getPin( "30" );
|
|
||||||
KIBIS_PIN* pin2 = comp.getPin( "31" );
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << "pin1 name: " << pin1->m_signalName << std::endl;
|
std::cout << "pin1 name: " << pin1->m_signalName << std::endl;
|
||||||
|
@ -42,13 +40,14 @@ int main( void )
|
||||||
|
|
||||||
std::cout << "WAVEFORM TYPE IN QA: " << wave->GetType() << std::endl;
|
std::cout << "WAVEFORM TYPE IN QA: " << wave->GetType() << std::endl;
|
||||||
std::cout << pin2->m_models.at(0)->m_name << std::endl;
|
std::cout << pin2->m_models.at(0)->m_name << std::endl;
|
||||||
pin2->writeSpiceDevice( tmp4, "device_typ", *( pin2->m_models.at( 0 ) ), IBIS_CORNER::TYP,
|
|
||||||
IBIS_CORNER::TYP );
|
KIBIS_PARAMETER params;
|
||||||
|
|
||||||
|
pin2->writeSpiceDevice( tmp4, "device_typ", *( pin2->m_models.at( 0 ) ), params );
|
||||||
|
|
||||||
KIBIS_MODEL* model1 = pin1->m_models.at( 0 );
|
KIBIS_MODEL* model1 = pin1->m_models.at( 0 );
|
||||||
std::cout << "Model used for driver: " << model1->m_name << std::endl;
|
std::cout << "Model used for driver: " << model1->m_name << std::endl;
|
||||||
pin1->writeSpiceDiffDriver( tmp1, "driver_typ", *( model1 ), IBIS_CORNER::TYP, IBIS_CORNER::TYP,
|
pin1->writeSpiceDiffDriver( tmp1, "driver_typ", *( model1 ), params );
|
||||||
KIBIS_ACCURACY::LEVEL_2, wave );
|
|
||||||
|
|
||||||
wxTextFile file( "output.sp" );
|
wxTextFile file( "output.sp" );
|
||||||
if( file.Exists() )
|
if( file.Exists() )
|
||||||
|
|
Loading…
Reference in New Issue