Sim: Ibis improvements and fixes

Follow-up after the KIBIS and KIBIS GUI merge requests.

- Move KIBIS from Pcbnew to Eeschema space,
- Make KIBIS obtain the Ku/Kd coefficients via the `SPICE_SIMULATOR` class instead of calling the `ngspice` executable via `system()`,
- Allow to toggle between differential and single-ended model in the GUI,
- Various GUI fixes and improvements.
This commit is contained in:
Fabien Corona 2022-10-25 09:45:40 +00:00 committed by Mikolaj Wielgus
parent 6794b0f4f9
commit 20b63f305e
21 changed files with 478 additions and 206 deletions

View File

@ -35,7 +35,7 @@ Licensed in the public domain:
Licensed under CC BY-SA 4.0:
- All the demo files provided in demos/*
Licensed under clause-3 BSD:
- ibis / kibis files in pcbnew/signalIntegrity
- ibis / kibis files in eeschema/sim/kibis
Licensed under CC0
- uopamp.lib.spice in some directories in qa/data/eeschema/spice_netlists/
Licensed under GPLv3 (or later):

View File

@ -276,8 +276,6 @@ set( EESCHEMA_SRCS
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.
sim/sim_library.cpp
@ -305,6 +303,9 @@ set( EESCHEMA_SRCS
sim/spice_library_parser.cpp
sim/spice_model_parser.cpp
sim/kibis/ibis_parser.cpp
sim/kibis/kibis.cpp
tools/assign_footprints.cpp
tools/backannotate.cpp
tools/ee_actions.cpp

View File

@ -165,6 +165,17 @@ bool DIALOG_SIM_MODEL<T>::TransferDataToWindow()
m_ibisModelCombobox->SetStringSelection(
SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD ) );
}
if( SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1" )
{
kibismodel->SwitchSingleEndedDiff( true );
m_differentialCheckbox->SetValue( true );
}
else
{
kibismodel->SwitchSingleEndedDiff( false );
m_differentialCheckbox->SetValue( false );
}
}
}
}
@ -235,13 +246,16 @@ bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
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() ) );
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD,
( kibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ) ? "1"
: "" );
}
}
@ -280,12 +294,47 @@ void DIALOG_SIM_MODEL<T>::updateWidgets()
template <typename T>
void DIALOG_SIM_MODEL<T>::updateIbisWidgets()
{
SIM_MODEL_KIBIS* modelkibis = nullptr;
if( isIbisLoaded() )
{
modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
for ( auto& item : m_sourceSizer->GetChildren() )
{
if ( item->GetWindow() == m_differentialCheckbox )
{
item->SetFlag( wxALIGN_CENTER_VERTICAL|wxALL|wxRESERVE_SPACE_EVEN_IF_HIDDEN );
}
if ( item->GetWindow() == m_overrideCheckbox )
{
item->SetFlag( wxALIGN_CENTER_VERTICAL|wxALL );
}
}
}
else
{
for ( auto& item : m_sourceSizer->GetChildren() )
{
if ( item->GetWindow() == m_differentialCheckbox )
{
item->SetFlag( wxALIGN_CENTER_VERTICAL|wxALL );
}
if ( item->GetWindow() == m_overrideCheckbox )
{
item->SetFlag( wxALIGN_CENTER_VERTICAL|wxALL|wxRESERVE_SPACE_EVEN_IF_HIDDEN );
}
}
}
m_ibisModelCombobox->Show( isIbisLoaded() );
m_ibisPinCombobox->Show( isIbisLoaded() );
m_ibisModelLabel->Show( isIbisLoaded() );
m_ibisPinLabel->Show( isIbisLoaded() );
m_overrideCheckbox->Show( !isIbisLoaded() );
m_differentialCheckbox->Show( isIbisLoaded() && modelkibis && modelkibis->CanDifferential() );
m_modelNameLabel->SetLabel( isIbisLoaded() ? "Component:" : "Model:" );
}
@ -554,6 +603,7 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
{
wxString ibisTypeString = SIM_MODEL::GetFieldValue( &m_fields, SIM_MODEL::TYPE_FIELD );
SIM_MODEL::TYPE ibisType = SIM_MODEL::TYPE::KIBIS_DEVICE;
if( ibisTypeString == "IBISDRIVERDC" )
@ -562,10 +612,6 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
ibisType = SIM_MODEL::TYPE::KIBIS_DRIVER_RECT;
else if( ibisTypeString == "IBISDRIVRPRBS" )
ibisType = SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS;
else if( ibisTypeString == "IBISDIFFDEVICE" )
ibisType = SIM_MODEL::TYPE::KIBIS_DIFFDEVICE;
else if( ibisTypeString == "IBISDIFFDRIVER" )
ibisType = SIM_MODEL::TYPE::KIBIS_DIFFDRIVER;
std::dynamic_pointer_cast<SIM_LIBRARY_KIBIS>( m_library )
->ReadFile( std::string( absolutePath.ToUTF8() ), ibisType );
@ -986,8 +1032,13 @@ void DIALOG_SIM_MODEL<T>::onIbisPinCombobox( wxCommandEvent& aEvent )
}
std::vector<std::pair<std::string, std::string>> strs = modelkibis->GetIbisPins();
std::string pinNumber = strs.at( m_ibisPinCombobox->GetSelection() ).first;
modelkibis->ChangePin( *std::dynamic_pointer_cast<SIM_LIBRARY_KIBIS>( m_library ),
strs.at( m_ibisPinCombobox->GetSelection() ).first );
pinNumber );
modelkibis->m_enableDiff = dynamic_cast<SIM_LIBRARY_KIBIS*>( m_library.get() )
->isPinDiff( modelkibis->GetComponentName(), pinNumber );
for( wxString modelName : modelkibis->GetIbisModels() )
modelLabels.Add( modelName );
@ -1030,6 +1081,18 @@ void DIALOG_SIM_MODEL<T>::onOverrideCheckbox( wxCommandEvent& aEvent )
updateWidgets();
}
template <typename T>
void DIALOG_SIM_MODEL<T>::onDifferentialCheckbox( wxCommandEvent& aEvent )
{
if( isIbisLoaded() )
{
SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
bool diff = m_differentialCheckbox->GetValue() && modelkibis->CanDifferential();
modelkibis->SwitchSingleEndedDiff( diff );
}
updateWidgets();
}
template <typename T>
void DIALOG_SIM_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
@ -1059,9 +1122,7 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
&& ( type == SIM_MODEL::TYPE::KIBIS_DEVICE
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_DC
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_RECT
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS
|| type == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE
|| type == SIM_MODEL::TYPE::KIBIS_DIFFDRIVER ) )
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER_PRBS ) )
{
std::shared_ptr<SIM_MODEL_KIBIS> kibismodel =
std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
@ -1070,12 +1131,6 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
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;

View File

@ -24,7 +24,7 @@
#ifndef DIALOG_SIM_MODEL_H
#define DIALOG_SIM_MODEL_H
#include <../../pcbnew/ibis/kibis.h>
#include <sim/kibis/kibis.h>
#include <dialog_sim_model_base.h>
#include <netlist_exporter_spice.h>
@ -123,6 +123,7 @@ private:
void onOverrideCheckboxUpdate( wxUpdateUIEvent& aEvent ) override;
void onDeviceTypeChoiceUpdate( wxUpdateUIEvent& aEvent ) override;
void onTypeChoiceUpdate( wxUpdateUIEvent& aEvent ) override;
void onDifferentialCheckbox( wxCommandEvent& event ) override;
void onParamGridSetFocus( wxFocusEvent& aEvent );
void onParamGridSelectionChange( wxPropertyGridEvent& aEvent );

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.0-4761b0c5)
// C++ code generated with wxFormBuilder (version 3.10.1-88b0f50)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -23,68 +23,66 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
wxBoxSizer* bSizer9;
bSizer9 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer4;
sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, _("Source") ), wxVERTICAL );
m_sourceStaticSizer = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, _("Source") ), wxVERTICAL );
wxFlexGridSizer* fgSizer15;
fgSizer15 = new wxFlexGridSizer( 0, 4, 0, 0 );
fgSizer15->AddGrowableCol( 2 );
fgSizer15->SetFlexibleDirection( wxBOTH );
fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_sourceSizer = new wxFlexGridSizer( 0, 4, 0, 0 );
m_sourceSizer->AddGrowableCol( 2 );
m_sourceSizer->SetFlexibleDirection( wxBOTH );
m_sourceSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_useInstanceModelRadioButton = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("Instance"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
fgSizer15->Add( m_useInstanceModelRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_useInstanceModelRadioButton = new wxRadioButton( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, _("Instance"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
m_sourceSizer->Add( m_useInstanceModelRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_useLibraryModelRadioButton = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, _("Library:"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer15->Add( m_useLibraryModelRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_useLibraryModelRadioButton = new wxRadioButton( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, _("Library:"), wxDefaultPosition, wxDefaultSize, 0 );
m_sourceSizer->Add( m_useLibraryModelRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_tclibraryPathName = new wxTextCtrl( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
fgSizer15->Add( m_tclibraryPathName, 0, wxEXPAND|wxALL, 5 );
m_tclibraryPathName = new wxTextCtrl( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
m_sourceSizer->Add( m_tclibraryPathName, 0, wxEXPAND|wxALL, 5 );
m_browseButton = new wxBitmapButton( sbSizer4->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
fgSizer15->Add( m_browseButton, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
m_browseButton = new wxBitmapButton( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_sourceSizer->Add( m_browseButton, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
m_sourceSizer->Add( 0, 0, 1, wxEXPAND, 5 );
m_modelNameLabel = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Model:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
m_modelNameLabel = new wxStaticText( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, _("Model:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
m_modelNameLabel->Wrap( -1 );
fgSizer15->Add( m_modelNameLabel, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 );
m_sourceSizer->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 );
fgSizer15->Add( m_modelNameCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
m_modelNameCombobox = new wxComboBox( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
m_sourceSizer->Add( m_modelNameCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
m_overrideCheckbox = new wxCheckBox( sbSizer4->GetStaticBox(), wxID_ANY, _("Override"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer15->Add( m_overrideCheckbox, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_overrideCheckbox = new wxCheckBox( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, _("Override"), wxDefaultPosition, wxDefaultSize, 0 );
m_sourceSizer->Add( m_overrideCheckbox, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
m_sourceSizer->Add( 0, 0, 1, wxEXPAND, 5 );
m_ibisPinLabel = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Pin:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
m_ibisPinLabel = new wxStaticText( m_sourceStaticSizer->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_sourceSizer->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 );
m_ibisPinCombobox = new wxComboBox( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
m_sourceSizer->Add( m_ibisPinCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
m_differentialCheckbox = new wxCheckBox( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, _("Differential"), wxDefaultPosition, wxDefaultSize, 0 );
m_sourceSizer->Add( m_differentialCheckbox, 0, wxALL, 5 );
fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
m_sourceSizer->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 = new wxStaticText( m_sourceStaticSizer->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_sourceSizer->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 );
m_ibisModelCombobox = new wxComboBox( m_sourceStaticSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
m_sourceSizer->Add( m_ibisModelCombobox, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
sbSizer4->Add( fgSizer15, 0, wxEXPAND, 5 );
m_sourceStaticSizer->Add( m_sourceSizer, 0, wxEXPAND, 5 );
bSizer9->Add( sbSizer4, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 );
bSizer9->Add( m_sourceStaticSizer, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 );
wxStaticBoxSizer* sbSizer5;
sbSizer5 = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, _("Model") ), wxVERTICAL );
@ -279,6 +277,8 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
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_differentialCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onDifferentialCheckbox ), NULL, this );
m_differentialCheckbox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckboxUpdate ), 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 );
@ -313,6 +313,8 @@ DIALOG_SIM_MODEL_BASE::~DIALOG_SIM_MODEL_BASE()
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_differentialCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onDifferentialCheckbox ), NULL, this );
m_differentialCheckbox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onOverrideCheckboxUpdate ), 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 );

View File

@ -186,31 +186,31 @@
<property name="id">wxID_ANY</property>
<property name="label">Source</property>
<property name="minimum_size"></property>
<property name="name">sbSizer4</property>
<property name="name">m_sourceStaticSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<property name="permission">protected</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="1">
<object class="wxFlexGridSizer" expanded="0">
<property name="cols">4</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">2</property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">fgSizer15</property>
<property name="name">m_sourceSizer</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">none</property>
<property name="permission">protected</property>
<property name="rows">0</property>
<property name="vgap">0</property>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<object class="wxRadioButton" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -271,11 +271,11 @@
<event name="OnRadioButton">onRadioButton</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<object class="wxRadioButton" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -336,11 +336,11 @@
<event name="OnRadioButton">onRadioButton</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1">
<object class="wxTextCtrl" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -401,11 +401,11 @@
<event name="OnUpdateUI">onLibraryPathUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<object class="wxBitmapButton" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -476,11 +476,11 @@
<event name="OnUpdateUI">onBrowseButtonUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<object class="spacer" expanded="0">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
@ -547,11 +547,11 @@
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxComboBox" expanded="1">
<object class="wxComboBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -616,11 +616,11 @@
<event name="OnUpdateUI">onModelNameComboboxUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<object class="wxCheckBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -682,21 +682,21 @@
<event name="OnUpdateUI">onOverrideCheckboxUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<object class="spacer" expanded="0">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<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">
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -753,11 +753,11 @@
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxComboBox" expanded="1">
<object class="wxComboBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -822,31 +822,87 @@
<event name="OnUpdateUI">onModelNameComboboxUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="0">
<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="checked">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">Differential</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_differentialCheckbox</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"></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="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">onDifferentialCheckbox</event>
<event name="OnUpdateUI">onOverrideCheckboxUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<object class="spacer" expanded="0">
<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">
<object class="sizeritem" expanded="0">
<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">
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -903,11 +959,11 @@
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxComboBox" expanded="1">
<object class="wxComboBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.0-4761b0c5)
// C++ code generated with wxFormBuilder (version 3.10.1-88b0f50)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -54,6 +54,8 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
protected:
wxNotebook* m_notebook;
wxPanel* m_modelPanel;
wxStaticBoxSizer* m_sourceStaticSizer;
wxFlexGridSizer* m_sourceSizer;
wxRadioButton* m_useInstanceModelRadioButton;
wxRadioButton* m_useLibraryModelRadioButton;
wxTextCtrl* m_tclibraryPathName;
@ -63,6 +65,7 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
wxCheckBox* m_overrideCheckbox;
wxStaticText* m_ibisPinLabel;
wxComboBox* m_ibisPinCombobox;
wxCheckBox* m_differentialCheckbox;
wxStaticText* m_ibisModelLabel;
wxComboBox* m_ibisModelCombobox;
wxNotebook* m_notebook4;
@ -97,6 +100,7 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
virtual void onOverrideCheckboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onIbisPinCombobox( wxCommandEvent& event ) { event.Skip(); }
virtual void onIbisPinComboboxTextEnter( wxCommandEvent& event ) { event.Skip(); }
virtual void onDifferentialCheckbox( 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(); }

View File

@ -23,7 +23,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <../../pcbnew/ibis/kibis.h>
#include <sim/kibis/kibis.h>
#include "netlist_exporter_spice.h"
#include <sim/sim_library_spice.h>
#include <sim/sim_model_raw_spice.h>
@ -403,7 +403,9 @@ void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSym
}
auto spiceGenerator = static_cast<const SPICE_GENERATOR_KIBIS&>( kibisModel->SpiceGenerator() );
std::string modelData = spiceGenerator.IbisDevice( aItem );
std::string modelData = spiceGenerator.IbisDevice(
aItem, std::string( m_schematic->Prj().GetProjectPath().c_str() ),
std::string( cacheDir.GetPath( wxPATH_GET_SEPARATOR ) ).c_str() );
cacheFile.Write( wxString( modelData ) );
m_rawIncludes.insert( libraryPath );

View File

@ -303,14 +303,14 @@ std::string IVtable::Spice( int aN, std::string aPort1, std::string aPort2, std:
for( IVtableEntry& entry : m_entries )
{
result += doubleToString( entry.V );
result += " ";
result += "\n+";
}
result += "]\n+ y_array=[";
for( IVtableEntry& entry : m_entries )
{
result += doubleToString( entry.I.value[aCorner] );
result += " ";
result += "\n+";
}
result += "]\n+ input_domain=0.05 fraction=TRUE)\n\n";
}
@ -2284,6 +2284,7 @@ bool IbisParser::readDiffPin()
{
bool status = true;
m_lineIndex = 0; // rewind
IbisDiffPinEntry entry( m_reporter );
if( m_continue == IBIS_PARSER_CONTINUE::NONE ) // No info on first line
@ -2302,7 +2303,7 @@ bool IbisParser::readDiffPin()
Report( _( "Incorrect inv_pin name" ), RPT_SEVERITY_ERROR );
status = false;
}
if( status && readWord( entry.pinB ) )
if( status )
{
m_currentComponent->m_diffPin.m_entries.push_back( entry );
}
@ -2468,7 +2469,7 @@ bool IbisParser::onNewLine()
return true;
}
// No new keyword ? Then it is the continuatino of the previous one !
// No new keyword ? Then it is the continuation of the previous one !
switch( m_continue )
{
case IBIS_PARSER_CONTINUE::STRING:

View File

@ -32,6 +32,8 @@
#include "kibis.h"
#include "ibis_parser.h"
#include <sstream>
#include <sim/spice_simulator.h>
// _() is used here to mark translatable strings in IBIS_REPORTER::Report()
// However, currently non ASCII7 chars are nor correctly handled when printing messages
@ -70,11 +72,11 @@ KIBIS::KIBIS( std::string aFileName ) : KIBIS_ANY( this ), m_file( this )
{
IBIS_REPORTER reporter;
IbisParser parser( &reporter );
bool status = true;
parser.m_parrot = false;
parser.ParseFile( aFileName );
status &= parser.ParseFile( aFileName );
bool status = true;
status &= m_file.Init( parser );
@ -96,6 +98,18 @@ KIBIS::KIBIS( std::string aFileName ) : KIBIS_ANY( this ), m_file( this )
{
pin.m_parent = &( m_components.back() );
}
for( IbisDiffPinEntry dpEntry : iComponent.m_diffPin.m_entries )
{
KIBIS_PIN* pinA = m_components.back().GetPin( dpEntry.pinA );
KIBIS_PIN* pinB = m_components.back().GetPin( dpEntry.pinB );
if( pinA && pinB )
{
pinA->m_complementaryPin = pinB;
pinB->m_complementaryPin = pinA;
}
}
}
m_valid = status;
@ -520,7 +534,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
simul += std::to_string( i );
simul += " ";
simul += aNode2;
simul += " pwl ( ";
simul += " pwl ( \n+";
if( i != 0 )
{
@ -532,7 +546,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
simul += doubleToString( entry0.t + timing - deltaT );
simul += " ";
simul += "0";
simul += " ";
simul += "\n+";
}
for( VTtableEntry& entry : WF->m_table.m_entries )
@ -540,7 +554,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
simul += doubleToString( entry.t + timing );
simul += " ";
simul += doubleToString( entry.V.value[supply] - delta );
simul += " ";
simul += "\n+";
}
simul += ")\n";
}
@ -559,7 +573,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
{
simul += " v( stimuli";
simul += std::to_string( ii );
simul += " ) + ";
simul += " ) +\n+";
}
// Depending on the first bit, we add a different DC value
@ -632,29 +646,25 @@ std::string KIBIS_PIN::addDie( KIBIS_MODEL& aModel, KIBIS_PARAMETER& aParam, int
void KIBIS_PIN::getKuKdFromFile( std::string* aSimul )
{
// @TODO
// that's not the best way to do, but ¯\_(ツ)_/¯
std::ifstream in( "temp_input.spice" );
std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
if( std::remove( "temp_input.spice" ) )
{
Report( _( "Cannot remove temporary input file" ), RPT_SEVERITY_WARNING );
}
if( std::remove( "temp_ouput.spice" ) )
if( std::remove( outputFileName.c_str() ) )
{
Report( _( "Cannot remove temporary output file" ), RPT_SEVERITY_WARNING );
}
std::ofstream file( "temp_input.spice" );
file << *aSimul;
system( "ngspice temp_input.spice" );
std::shared_ptr<SPICE_SIMULATOR> ng = SIMULATOR::CreateInstance( "ng-kibis" );
if( !ng )
{
throw std::runtime_error( "Could not create simulator instance" );
return;
}
ng->Init();
ng->LoadNetlist( *aSimul );
std::ifstream KuKdfile;
KuKdfile.open( "temp_output.spice" );
KuKdfile.open( outputFileName );
std::vector<double> ku, kd, t;
if( KuKdfile )
@ -700,21 +710,14 @@ void KIBIS_PIN::getKuKdFromFile( std::string* aSimul )
}
else
{
Report( _( "Error while creating temporary file" ), RPT_SEVERITY_ERROR );
Report( _( "Error while creating temporary output file" ), RPT_SEVERITY_ERROR );
}
if( std::remove( "temp_input.spice" ) )
{
Report( _( "Cannot remove temporary input file" ), RPT_SEVERITY_WARNING );
}
if( std::remove( "temp_ouput.spice" ) )
if( std::remove( outputFileName.c_str() ) )
{
Report( _( "Cannot remove temporary output file" ), RPT_SEVERITY_WARNING );
}
// @TODO : this is the end of the dirty code
m_Ku = ku;
m_Kd = kd;
m_t = t;
@ -775,7 +778,6 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
{
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
{
std::vector<std::pair<int, double>> bits;
KIBIS_WAVEFORM_RECTANGULAR* rectWave = dynamic_cast<KIBIS_WAVEFORM_RECTANGULAR*>( wave );
if( !rectWave )
@ -792,26 +794,14 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
Report( _( "Falling edge is longer than off time." ), RPT_SEVERITY_WARNING );
}
for( int i = 0; i < rectWave->m_cycles; i++ )
{
std::pair<int, double> bit;
bit.first = rectWave->inverted ? 0 : 1;
bit.second = ( rectWave->m_ton + rectWave->m_toff ) * i + rectWave->m_delay;
bits.push_back( bit );
bit.first = rectWave->inverted ? 1 : 0;
bit.second = ( rectWave->m_ton + rectWave->m_toff ) * i + rectWave->m_delay
+ rectWave->m_ton;
bits.push_back( bit );
}
std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
break;
}
case KIBIS_WAVEFORM_TYPE::PRBS:
{
KIBIS_WAVEFORM_PRBS* prbsWave = dynamic_cast<KIBIS_WAVEFORM_PRBS*>( wave );
std::vector<std::pair<int, double>> bits = prbsWave->GenerateBitSequence();
std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
break;
}
@ -939,7 +929,9 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
simul += "run \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 += "write temp_output.spice v(KU) v(KD)\n"; // @TODO we might want to remove this...
std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
simul += "write " + outputFileName + " v(KU) v(KD)\n";
simul += "quit\n";
simul += ".endc \n";
simul += ".end \n";
@ -1144,7 +1136,8 @@ void KIBIS_PIN::getKuKdTwoWaveforms( KIBIS_MODEL& aMo
simul += "run \n";
simul += "plot v(KU) v(KD)\n";
//simul += "plot v(x1.DIE0) \n";
simul += "write temp_output.spice v(KU) v(KD)\n"; // @TODO we might want to remove this...
std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
simul += "write " + outputFileName + " v(KU) v(KD)\n";
simul += "quit\n";
simul += ".endc \n";
simul += ".end \n";
@ -1455,6 +1448,51 @@ void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, std::string aSt
aCorner = IBIS_CORNER::TYP;
}
std::vector<std::pair<int, double>> KIBIS_WAVEFORM_STUCK_HIGH::GenerateBitSequence()
{
std::vector<std::pair<int, double>> bits;
std::pair<int, double> bit;
bit.first = inverted ? 1 : 0;
bit.second = 0;
return bits;
}
std::vector<std::pair<int, double>> KIBIS_WAVEFORM_STUCK_LOW::GenerateBitSequence()
{
std::vector<std::pair<int, double>> bits;
std::pair<int, double> bit;
bit.first = inverted ? 0 : 1;
bit.second = 0;
return bits;
}
std::vector<std::pair<int, double>> KIBIS_WAVEFORM_HIGH_Z::GenerateBitSequence()
{
std::vector<std::pair<int, double>> bits;
return bits;
}
std::vector<std::pair<int, double>> KIBIS_WAVEFORM_RECTANGULAR::GenerateBitSequence()
{
std::vector<std::pair<int, double>> bits;
for( int i = 0; i < m_cycles; i++ )
{
std::pair<int, double> bit;
bit.first = inverted ? 0 : 1;
bit.second = ( m_ton + m_toff ) * i + m_delay;
bits.push_back( bit );
bit.first = inverted ? 1 : 0;
bit.second = ( m_ton + m_toff ) * i + m_delay + m_ton;
bits.push_back( bit );
}
return bits;
}
std::vector<std::pair<int, double>> KIBIS_WAVEFORM_PRBS::GenerateBitSequence()
{
std::vector<std::pair<int, double>> bitSequence;
@ -1487,5 +1525,4 @@ std::vector<std::pair<int, double>> KIBIS_WAVEFORM_PRBS::GenerateBitSequence()
} while ( ++bits < m_bits );
return bitSequence;
}
}

View File

@ -68,6 +68,12 @@ public:
bool inverted = false; // Used for differential drivers
virtual ~KIBIS_WAVEFORM(){};
virtual std::vector<std::pair<int, double>> GenerateBitSequence()
{
std::vector<std::pair<int, double>> bits;
return bits;
};
protected:
KIBIS_WAVEFORM_TYPE m_type = KIBIS_WAVEFORM_TYPE::NONE;
};
@ -81,6 +87,7 @@ public:
int m_cycles = 1;
double m_delay = 0;
std::vector<std::pair<int, double>> GenerateBitSequence() override;
double GetDuration() override { return ( m_ton + m_toff ) * m_cycles; };
};
@ -93,7 +100,7 @@ public:
double m_delay = 0;
double m_bits = 10;
std::vector<std::pair<int, double>> GenerateBitSequence();
std::vector<std::pair<int, double>> GenerateBitSequence() override;
double GetDuration() override { return m_bits / m_bitrate ; };
};
@ -101,18 +108,21 @@ class KIBIS_WAVEFORM_STUCK_HIGH : public KIBIS_WAVEFORM
{
public:
KIBIS_WAVEFORM_STUCK_HIGH() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::STUCK_HIGH; };
std::vector<std::pair<int, double>> GenerateBitSequence() override;
};
class KIBIS_WAVEFORM_STUCK_LOW : public KIBIS_WAVEFORM
{
public:
KIBIS_WAVEFORM_STUCK_LOW() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::STUCK_LOW; };
std::vector<std::pair<int, double>> GenerateBitSequence() override;
};
class KIBIS_WAVEFORM_HIGH_Z : public KIBIS_WAVEFORM
{
public:
KIBIS_WAVEFORM_HIGH_Z() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::HIGH_Z; };
std::vector<std::pair<int, double>> GenerateBitSequence() override;
};
/** Accuracy level.
@ -186,6 +196,9 @@ public:
std::vector<KIBIS_MODEL> m_models;
KIBIS_FILE m_file;
/** @brief Absolute path of the directory that will be used for caching. */
std::string m_cacheDir = "";
/** @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 */
@ -385,6 +398,10 @@ public:
* @param aSimul The simulation to run, multiline spice directives
*/
void getKuKdFromFile( std::string* aSimul );
KIBIS_PIN* m_complementaryPin = nullptr;
bool isDiffPin() { return m_complementaryPin != nullptr; };
};
class KIBIS_COMPONENT : public KIBIS_ANY

View File

@ -43,9 +43,6 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath, SIM_MODEL::TYPE
unsigned pinNumber = 2;
if( aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE || aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE )
pinNumber = 3;
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
{
m_models.push_back( SIM_MODEL::Create( aType, pinNumber ) );
@ -72,8 +69,22 @@ bool SIM_LIBRARY_KIBIS::InitModel( SIM_MODEL_KIBIS& aModel, wxString aCompName )
for( KIBIS_PIN& kpin : kcomp.m_pins )
{
aModel.m_ibisPins.emplace_back( kpin.m_pinNumber, kpin.m_signalName );
if( kpin.isDiffPin() )
m_diffPins.emplace_back( kcomp.m_name, kpin.m_pinNumber );
}
return true;
}
return false;
}
bool SIM_LIBRARY_KIBIS::isPinDiff( const std::string& aComp, const std::string& aPinNumber )
{
for( std::pair<std::string, std::string> aInfo : m_diffPins )
{
if( aInfo.first == aComp && aInfo.second == aPinNumber )
return true;
}
return false;
}

View File

@ -24,7 +24,7 @@
#ifndef SIM_LIBRARY_KIBIS_H
#define SIM_LIBRARY_KIBIS_H
#include <../../pcbnew/ibis/kibis.h>
#include <sim/kibis/kibis.h>
#include <sim/sim_library.h>
#include <sim/sim_model_kibis.h>
@ -35,6 +35,7 @@ class SIM_LIBRARY_KIBIS : public SIM_LIBRARY
public:
static constexpr auto PIN_FIELD = "Ibis_Pin";
static constexpr auto MODEL_FIELD = "Ibis_Model";
static constexpr auto DIFF_FIELD = "Ibis_Diff";
// @copydoc SIM_LIBRARY::ReadFile()
void ReadFile( const std::string& aFilePath, SIM_MODEL::TYPE aType );
@ -47,9 +48,11 @@ public:
void WriteFile( const std::string& aFilePath ) override{};
bool InitModel( SIM_MODEL_KIBIS& aModel, wxString aCompName );
bool isPinDiff( const std::string& aComp, const std::string& aPinNumber );
protected:
KIBIS m_kibis;
std::vector<std::pair<std::string, std::string>> m_diffPins;
};
#endif // SIM_LIBRARY_SPICE_H

View File

@ -36,6 +36,8 @@
#include <sim/sim_model_tline.h>
#include <sim/sim_model_xspice.h>
#include <sim/sim_library_kibis.h>
#include <lib_symbol.h>
#include <confirm.h>
@ -238,8 +240,6 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
case TYPE::KIBIS_DRIVER_DC: return { DEVICE_TYPE_::KIBIS, "IBISDRIVERDC", "DC driver" };
case TYPE::KIBIS_DRIVER_RECT: return { DEVICE_TYPE_::KIBIS, "IBISDRIVERRECT", "Rectangular wave driver" };
case TYPE::KIBIS_DRIVER_PRBS: return { DEVICE_TYPE_::KIBIS, "IBISDRIVERPRBS", "PRBS driver" };
case TYPE::KIBIS_DIFFDEVICE: return { DEVICE_TYPE_::KIBIS, "IBISDIFFDEVICE", "Differential device" };
case TYPE::KIBIS_DIFFDRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDIFFDRIVER", "Differential driver" };
case TYPE::RAWSPICE: return { DEVICE_TYPE_::SPICE, "", "" };
@ -376,8 +376,6 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
case TYPE::KIBIS_DRIVER_DC: return { "X" };
case TYPE::KIBIS_DRIVER_RECT: return { "X" };
case TYPE::KIBIS_DRIVER_PRBS: return { "X" };
case TYPE::KIBIS_DIFFDEVICE: return { "X" };
case TYPE::KIBIS_DIFFDRIVER: return { "X" };
case TYPE::NONE:
case TYPE::RAWSPICE:
@ -709,6 +707,11 @@ void SIM_MODEL::AddPin( const PIN& aPin )
m_pins.push_back( aPin );
}
void SIM_MODEL::DeletePins()
{
m_pins.clear();
}
int SIM_MODEL::FindModelPinIndex( const std::string& aSymbolPinNumber )
{
@ -949,8 +952,6 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType )
case TYPE::KIBIS_DRIVER_DC:
case TYPE::KIBIS_DRIVER_RECT:
case TYPE::KIBIS_DRIVER_PRBS:
case TYPE::KIBIS_DIFFDEVICE:
case TYPE::KIBIS_DIFFDRIVER:
return std::make_unique<SIM_MODEL_KIBIS>( aType );
case TYPE::RAWSPICE:

View File

@ -347,8 +347,6 @@ public:
KIBIS_DRIVER_DC,
KIBIS_DRIVER_RECT,
KIBIS_DRIVER_PRBS,
KIBIS_DIFFDEVICE,
KIBIS_DIFFDRIVER,
RAWSPICE
)
@ -545,6 +543,8 @@ public:
SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); }
void AddPin( const PIN& aPin );
void DeletePins();
int FindModelPinIndex( const std::string& aSymbolPinNumber );
void AddParam( const PARAM::INFO& aInfo, bool aIsOtherVariant = false );

View File

@ -21,12 +21,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <../../pcbnew/ibis/kibis.h>
#include <sim/kibis/kibis.h>
#include <sim/sim_model_kibis.h>
#include <sim/sim_library_kibis.h>
#include <paths.h>
#include <fmt/core.h>
#include <wx/filename.h>
#include <kiway.h>
std::string SPICE_GENERATOR_KIBIS::ModelName( const SPICE_ITEM& aItem ) const
{
@ -57,14 +58,29 @@ std::vector<std::string> SPICE_GENERATOR_KIBIS::CurrentNames( const SPICE_ITEM&
}
std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem ) const
std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const std::string aCwd,
const std::string aCacheDir ) const
{
std::string ibisLibFilename = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY::LIBRARY_FIELD );
std::string ibisCompName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY::NAME_FIELD );
std::string ibisPinName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::PIN_FIELD );
std::string ibisModelName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::MODEL_FIELD );
bool diffMode = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
wxFileName libPath = wxFileName( wxString( ibisLibFilename ) );
if( !libPath.IsAbsolute() )
libPath.MakeAbsolute( aCwd );
KIBIS kibis( std::string( libPath.GetAbsolutePath().c_str() ) );
kibis.m_cacheDir = aCacheDir;
if( !kibis.m_valid )
{
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS file '%s'" ),
ibisLibFilename ) );
}
KIBIS kibis( ibisLibFilename );
KIBIS_COMPONENT* kcomp = kibis.GetComponent( std::string( ibisCompName ) );
if( !kcomp )
@ -72,6 +88,13 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem ) const
KIBIS_PIN* kpin = kcomp->GetPin( ibisPinName );
if( !kcomp->m_valid )
{
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS component '%s'" ),
ibisCompName ) );
}
if( !kpin )
{
THROW_IO_ERROR( wxString::Format( _( "Could not find IBIS pin '%s' in component '%s'" ),
@ -107,7 +130,10 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem ) const
switch( m_model.GetType() )
{
case SIM_MODEL::TYPE::KIBIS_DEVICE:
kpin->writeSpiceDevice( &result, aItem.modelName, *kmodel, kparams );
if( diffMode )
kpin->writeSpiceDiffDevice( &result, aItem.modelName, *kmodel, kparams );
else
kpin->writeSpiceDevice( &result, aItem.modelName, *kmodel, kparams );
break;
case SIM_MODEL::TYPE::KIBIS_DRIVER_DC:
@ -130,7 +156,10 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem ) const
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH() );
}
kpin->writeSpiceDriver( &result, aItem.modelName, *kmodel, kparams );
if( diffMode )
kpin->writeSpiceDiffDriver( &result, aItem.modelName, *kmodel, kparams );
else
kpin->writeSpiceDriver( &result, aItem.modelName, *kmodel, kparams );
break;
}
@ -138,12 +167,24 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem ) const
{
KIBIS_WAVEFORM_RECTANGULAR* waveform = new KIBIS_WAVEFORM_RECTANGULAR();
waveform->m_ton = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "ton" )->value ).Get().value_or( 1 );
waveform->m_toff = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "toff" )->value ).Get().value_or( 1 );
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 );
if ( m_model.FindParam( "ton" ) )
waveform->m_ton = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "ton" )->value ).Get().value_or( 1 );
if ( m_model.FindParam( "toff" ) )
waveform->m_toff = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "toff" )->value ).Get().value_or( 1 );
if ( m_model.FindParam( "delay" ) )
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 );
if ( m_model.FindParam( "cycles" ) )
waveform->m_cycles = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "cycles" )->value ).Get().value_or( 0 );
kparams.m_waveform = waveform;
kpin->writeSpiceDriver( &result, aItem.modelName, *kmodel, kparams );
if( diffMode )
kpin->writeSpiceDiffDriver( &result, aItem.modelName, *kmodel, kparams );
else
kpin->writeSpiceDriver( &result, aItem.modelName, *kmodel, kparams );
break;
}
@ -151,12 +192,21 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem ) const
{
KIBIS_WAVEFORM_PRBS* waveform = new KIBIS_WAVEFORM_PRBS();
waveform->m_bitrate = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "f0" )->value ).Get().value_or( 0 );
if ( m_model.FindParam( "f0" ) )
waveform->m_bitrate = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "f0" )->value ).Get().value_or( 0 );
if ( m_model.FindParam( "bits" ) )
waveform->m_bits = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "bits" )->value ).Get().value_or( 0 );
if ( m_model.FindParam( "delay" ) )
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "delay" )->value ).Get().value_or( 0 );
kparams.m_waveform = waveform;
kpin->writeSpiceDriver( &result, aItem.modelName, *kmodel, kparams );
if( diffMode )
kpin->writeSpiceDiffDriver( &result, aItem.modelName, *kmodel, kparams );
else
kpin->writeSpiceDriver( &result, aItem.modelName, *kmodel, kparams );
break;
}
@ -195,7 +245,15 @@ SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType ) :
for( const PARAM::INFO& paramInfo : *paramInfos )
AddParam( paramInfo );
if( aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE || aType == SIM_MODEL::TYPE::KIBIS_DIFFDRIVER )
SwitchSingleEndedDiff( false );
}
void SIM_MODEL_KIBIS::SwitchSingleEndedDiff( bool aDiff )
{
DeletePins();
if( aDiff )
{
AddPin( { "GND", "1" } );
AddPin( { "+", "2" } );
@ -208,7 +266,6 @@ SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType ) :
}
}
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) : SIM_MODEL_KIBIS( aType )
{
for( PARAM& param1 : m_params )
@ -405,7 +462,15 @@ std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_KIBIS::makeRectWaveformParamInfos(
paramInfo.defaultValue = "0";
paramInfo.description = _( "Delay" );
paramInfos.push_back( paramInfo );
paramInfo.name = "cycles";
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.unit = "";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = "1";
paramInfo.description = _( "cycles" );
paramInfos.push_back( paramInfo );
return paramInfos;
}
@ -433,3 +498,20 @@ std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_KIBIS::makePrbsWaveformParamInfos(
return paramInfos;
}
void SIM_MODEL_KIBIS::ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields )
{
bool diffMode = SIM_MODEL::GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
SwitchSingleEndedDiff( diffMode );
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
}
void SIM_MODEL_KIBIS::ReadDataLibFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields )
{
bool diffMode = SIM_MODEL::GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
SwitchSingleEndedDiff( diffMode );
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
}

View File

@ -24,7 +24,7 @@
#ifndef SIM_MODEL_KIBIS_H
#define SIM_MODEL_KIBIS_H
#include <../../pcbnew/ibis/kibis.h>
#include <sim/kibis/kibis.h>
#include <sim/sim_model.h>
#include <sim/spice_generator.h>
#include <project.h>
@ -41,7 +41,8 @@ public:
std::string ModelLine( const SPICE_ITEM& aItem ) const override;
std::vector<std::string> CurrentNames( const SPICE_ITEM& aItem ) const override;
std::string IbisDevice( const SPICE_ITEM& aItem ) const;
std::string IbisDevice( const SPICE_ITEM& aItem, const std::string aCwd,
const std::string aCacheDir ) const;
protected:
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const override;
@ -88,6 +89,13 @@ public:
void SetBaseModel( const SIM_MODEL& aBaseModel ) override;
void SwitchSingleEndedDiff( bool aDiff );
bool CanDifferential() { return m_enableDiff; };
bool m_enableDiff;
void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields ) override;
void ReadDataLibFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields ) override;
protected:
void CreatePins( unsigned aSymbolPinCount ) override;

View File

@ -49,5 +49,5 @@ add_subdirectory( unittests )
add_subdirectory( tools )
if( KICAD_SIGNAL_INTEGRITY )
add_subdirectory( ibis )
#add_subdirectory( ibis )
endif()

View File

@ -25,40 +25,32 @@ find_package(Boost COMPONENTS unit_test_framework REQUIRED)
find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED )
add_definitions(-DBOOST_TEST_DYN_LINK -DPCBNEW -DDRC_PROTO -DTEST_APP_NO_MAIN)
add_definitions(-DBOOST_TEST_DYN_LINK -DEESCHEMA -DDRC_PROTO -DTEST_APP_NO_MAIN)
add_executable( ibis_proto
qaIbisParser.cpp
${CMAKE_SOURCE_DIR}/pcbnew/ibis/ibis_parser.cpp
${CMAKE_SOURCE_DIR}/pcbnew/ibis/kibis.cpp
${CMAKE_SOURCE_DIR}/eeschema/sim/kibis/ibis_parser.cpp
${CMAKE_SOURCE_DIR}/eeschema/sim/kibis/kibis.cpp
${CMAKE_SOURCE_DIR}/eeschema/sim/ngspice_helpers.cpp
${CMAKE_SOURCE_DIR}/eeschema/sim/ngspice.cpp
)
add_dependencies( ibis_proto pnsrouter pcbcommon ${PCBNEW_IO_LIBRARIES} )
add_dependencies( ibis_proto pnsrouter pcbcommon )
include_directories( BEFORE ${INC_BEFORE} )
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/3d-viewer
${CMAKE_SOURCE_DIR}/common
${CMAKE_SOURCE_DIR}/pcbnew
${CMAKE_SOURCE_DIR}/pcbnew/router
${CMAKE_SOURCE_DIR}/pcbnew/tools
${CMAKE_SOURCE_DIR}/pcbnew/dialogs
${CMAKE_SOURCE_DIR}/polygon
${CMAKE_SOURCE_DIR}/common/geometry
${CMAKE_SOURCE_DIR}/libs/kimath/include/math
${CMAKE_SOURCE_DIR}/qa/common
${CMAKE_SOURCE_DIR}/qa
${CMAKE_SOURCE_DIR}/qa/qa_utils
${CMAKE_SOURCE_DIR}/qa/qa_utils/include
${CMAKE_SOURCE_DIR}/qa/pcbnew_utils/include
${CMAKE_SOURCE_DIR}/eeschema
${CMAKE_SOURCE_DIR}/eeschema/sim
${CMAKE_SOURCE_DIR}/qa/eeschema_utils/include
${Boost_INCLUDE_DIR}
${INC_AFTER}
)
target_link_libraries( ibis_proto
qa_pcbnew_utils
qa_eechema_utils
3d-viewer
connectivity
pcbcommon
@ -71,12 +63,11 @@ target_link_libraries( ibis_proto
tinyspline_lib
nanosvg
idf3
${PCBNEW_IO_LIBRARIES}
${wxWidgets_LIBRARIES}
${GDI_PLUS_LIBRARIES}
${PYTHON_LIBRARIES}
${Boost_LIBRARIES}
${PCBNEW_EXTRA_LIBS} # -lrt must follow Boost
${EESCHEMA_EXTRA_LIBS} # -lrt must follow Boost
)
configure_file( "ibis_v1_1.ibs" "ibis_v1_1.ibs" COPYONLY )

View File

@ -1,4 +1,4 @@
#include "../../pcbnew/ibis/kibis.h"
#include "../../eeschema/sim/kibis/kibis.h"
#include <wx/textfile.h>
int main( void )