Add Ibis to spice model editor

ADDED: IBIS models are now supported in Sim Model Editor
This commit is contained in:
Fabien Corona 2022-09-27 20:47:00 +00:00 committed by Mikolaj Wielgus
parent 1a812727cb
commit 528fe4d371
23 changed files with 1673 additions and 157 deletions

View File

@ -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

View File

@ -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>;

View File

@ -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 */

View File

@ -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 );

View File

@ -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>

View File

@ -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(); }

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}; };

View File

@ -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>();

View File

@ -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;
}; };

View File

@ -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;
}

View File

@ -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

View File

@ -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" );

View File

@ -87,7 +87,8 @@ protected:
B3SOIPD, B3SOIPD,
HISIM2, HISIM2,
HISIMHV1, HISIMHV1,
HISIMHV2 HISIMHV2,
KIBIS
) )
struct MODEL_INFO struct MODEL_INFO

View File

@ -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();

View File

@ -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;
}; };

View File

@ -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;
}

View File

@ -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

View File

@ -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() )