Sim Model Editor: Serialize models in fields
Implemented serialization and deserialization of models in symbol fields through the SIM_VALUE class. We don't carry the Spice legacy of case-insensitive suffixes, instead we conform to the SI standard (i.e. M is Mega, not milli, P is peta, p is pico). Parameter grid value validation is implemented by simply not allowing any characters that will make the value invalid (instead of highlighting the field in a red color). This will likely be changed at some point in the future.
This commit is contained in:
parent
c5a256291e
commit
978f01553b
|
@ -318,6 +318,7 @@ if( KICAD_SPICE )
|
|||
sim/sim_plot_frame.cpp
|
||||
sim/sim_plot_frame_base.cpp
|
||||
sim/sim_plot_panel.cpp
|
||||
sim/sim_property.cpp
|
||||
sim/sim_workbook.cpp
|
||||
sim/sim_model.cpp
|
||||
sim/sim_model_behavioral.cpp
|
||||
|
|
|
@ -22,9 +22,12 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <widgets/wx_grid.h>
|
||||
#include <dialog_spice_model.h>
|
||||
#include <sim/sim_property.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
#include <kiplatform/ui.h>
|
||||
#include <confirm.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
using TYPE = SIM_VALUE_BASE::TYPE;
|
||||
using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
|
||||
|
@ -49,11 +52,12 @@ DIALOG_SPICE_MODEL<T>::DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbo
|
|||
{
|
||||
if( type == typeFromFields )
|
||||
{
|
||||
m_models.push_back( SIM_MODEL::Create( aFields ) );
|
||||
m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size(),
|
||||
&aFields ) );
|
||||
m_curModelType = type;
|
||||
}
|
||||
else
|
||||
m_models.push_back( SIM_MODEL::Create( type ) );
|
||||
m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size() ) );
|
||||
|
||||
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( type ).deviceType;
|
||||
|
||||
|
@ -74,11 +78,38 @@ DIALOG_SPICE_MODEL<T>::DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbo
|
|||
for( SIM_MODEL::DEVICE_TYPE deviceType : SIM_MODEL::DEVICE_TYPE_ITERATOR() )
|
||||
m_deviceTypeChoice->Append( SIM_MODEL::DeviceTypeInfo( deviceType ).description );
|
||||
|
||||
m_paramGrid = m_paramGridMgr->AddPage();
|
||||
|
||||
|
||||
m_scintillaTricks = std::make_unique<SCINTILLA_TRICKS>( m_codePreview, wxT( "{}" ), false );
|
||||
|
||||
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SPICE_MODEL::onSelectionChange, this );
|
||||
|
||||
m_paramGrid->SetValidationFailureBehavior( wxPG_VFB_STAY_IN_PROPERTY
|
||||
| wxPG_VFB_BEEP
|
||||
| wxPG_VFB_MARK_CELL );
|
||||
|
||||
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::DESCRIPTION ), 50 );
|
||||
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::VALUE ), 18 );
|
||||
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::UNIT ), 10 );
|
||||
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::DEFAULT ), 12 );
|
||||
m_paramGrid->SetColumnProportion( static_cast<int>( PARAM_COLUMN::TYPE ), 10 );
|
||||
|
||||
if( wxPropertyGrid* grid = m_paramGrid->GetGrid() )
|
||||
{
|
||||
grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
|
||||
grid->DedicateKey( WXK_RETURN );
|
||||
grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
|
||||
|
||||
grid->DedicateKey( WXK_UP );
|
||||
grid->DedicateKey( WXK_DOWN );
|
||||
|
||||
// Doesn't work for some reason.
|
||||
//grid->DedicateKey( WXK_TAB );
|
||||
//grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_TAB );
|
||||
//grid->AddActionTrigger( wxPG_ACTION_PREV_PROPERTY, WXK_TAB, wxMOD_SHIFT );
|
||||
}
|
||||
else
|
||||
wxFAIL;
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
|
@ -89,7 +120,7 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataFromWindow()
|
|||
if( !DIALOG_SPICE_MODEL_BASE::TransferDataFromWindow() )
|
||||
return false;
|
||||
|
||||
m_models[static_cast<int>( m_curModelType )]->WriteFields( m_fields );
|
||||
getCurModel().WriteFields( m_fields );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -100,8 +131,8 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow()
|
|||
{
|
||||
try
|
||||
{
|
||||
m_models[static_cast<int>( SIM_MODEL::ReadTypeFromFields( m_fields ) )]
|
||||
= SIM_MODEL::Create( m_fields );
|
||||
m_models.at( static_cast<int>( SIM_MODEL::ReadTypeFromFields( m_fields ) ) )
|
||||
= SIM_MODEL::Create( m_symbol.GetAllPins().size(), m_fields );
|
||||
}
|
||||
catch( KI_PARAM_ERROR& e )
|
||||
{
|
||||
|
@ -117,6 +148,15 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow()
|
|||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::updateWidgets()
|
||||
{
|
||||
updateModelParamsTab();
|
||||
updateModelCodeTab();
|
||||
updatePinAssignmentsTab();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::updateModelParamsTab()
|
||||
{
|
||||
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( m_curModelType ).deviceType;
|
||||
|
||||
|
@ -141,11 +181,11 @@ void DIALOG_SPICE_MODEL<T>::updateWidgets()
|
|||
|
||||
// This wxPropertyGridManager stuff has to be here because it segfaults in the constructor.
|
||||
|
||||
m_paramGridMgr->SetColumnCount( static_cast<int>( COLUMN::END_ ) );
|
||||
m_paramGridMgr->SetColumnCount( static_cast<int>( PARAM_COLUMN::END_ ) );
|
||||
|
||||
m_paramGridMgr->SetColumnTitle( static_cast<int>( COLUMN::UNIT ), "Unit" );
|
||||
m_paramGridMgr->SetColumnTitle( static_cast<int>( COLUMN::DEFAULT ), "Default" );
|
||||
m_paramGridMgr->SetColumnTitle( static_cast<int>( COLUMN::TYPE ), "Type" );
|
||||
m_paramGridMgr->SetColumnTitle( static_cast<int>( PARAM_COLUMN::UNIT ), "Unit" );
|
||||
m_paramGridMgr->SetColumnTitle( static_cast<int>( PARAM_COLUMN::DEFAULT ), "Default" );
|
||||
m_paramGridMgr->SetColumnTitle( static_cast<int>( PARAM_COLUMN::TYPE ), "Type" );
|
||||
|
||||
m_paramGridMgr->ShowHeader();
|
||||
|
||||
|
@ -176,9 +216,7 @@ void DIALOG_SPICE_MODEL<T>::updateWidgets()
|
|||
m_paramGrid->Append( new wxPropertyCategory( "Flags" ) );
|
||||
m_paramGrid->HideProperty( "Flags" );
|
||||
|
||||
SIM_MODEL& curModel = *m_models[static_cast<int>( m_curModelType )];
|
||||
|
||||
for( const SIM_MODEL::PARAM& param : curModel.Params() )
|
||||
for( const SIM_MODEL::PARAM& param : getCurModel().Params() )
|
||||
addParamPropertyIfRelevant( param );
|
||||
|
||||
m_paramGrid->CollapseAll();
|
||||
|
@ -186,36 +224,107 @@ void DIALOG_SPICE_MODEL<T>::updateWidgets()
|
|||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
|
||||
void DIALOG_SPICE_MODEL<T>::updateModelCodeTab()
|
||||
{
|
||||
SIM_MODEL::DEVICE_TYPE deviceType =
|
||||
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
|
||||
|
||||
m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
|
||||
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
||||
void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsTab()
|
||||
{
|
||||
SIM_MODEL::DEVICE_TYPE deviceType =
|
||||
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
|
||||
wxString typeDescription = m_typeChoice->GetString( m_typeChoice->GetSelection() );
|
||||
m_pinAssignmentsGrid->ClearRows();
|
||||
|
||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||
std::vector<SCH_PIN*> pinList = m_symbol.GetAllPins();
|
||||
|
||||
m_pinAssignmentsGrid->AppendRows( static_cast<int>( pinList.size() ) );
|
||||
|
||||
for( int i = 0; i < m_pinAssignmentsGrid->GetNumberRows(); ++i )
|
||||
{
|
||||
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
|
||||
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
||||
{
|
||||
m_curModelType = type;
|
||||
break;
|
||||
}
|
||||
wxString symbolPinString = getSymbolPinString( i + 1 );
|
||||
|
||||
m_pinAssignmentsGrid->SetReadOnly( i, static_cast<int>( PIN_COLUMN::SYMBOL ) );
|
||||
m_pinAssignmentsGrid->SetCellValue( i, static_cast<int>( PIN_COLUMN::SYMBOL ),
|
||||
symbolPinString );
|
||||
|
||||
// Using `new` here shouldn't cause a memory leak because `SetCellEditor()` calls
|
||||
// `DecRef()` on its last editor.
|
||||
m_pinAssignmentsGrid->SetCellEditor( i, static_cast<int>( PIN_COLUMN::MODEL ),
|
||||
new wxGridCellChoiceEditor() );
|
||||
m_pinAssignmentsGrid->SetCellValue( i, static_cast<int>( PIN_COLUMN::MODEL ),
|
||||
"Not Connected" );
|
||||
}
|
||||
|
||||
m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
|
||||
updateWidgets();
|
||||
for( unsigned int i = 0; i < getCurModel().Pins().size(); ++i )
|
||||
{
|
||||
int symbolPinNumber = getCurModel().Pins().at( i ).symbolPinNumber;
|
||||
|
||||
if( symbolPinNumber == SIM_MODEL::PIN::NOT_CONNECTED )
|
||||
continue;
|
||||
|
||||
wxString modelPinString = getModelPinString( i + 1 );
|
||||
wxArrayString choices;
|
||||
|
||||
m_pinAssignmentsGrid->SetCellValue( symbolPinNumber - 1,
|
||||
static_cast<int>( PIN_COLUMN::MODEL ),
|
||||
modelPinString );
|
||||
}
|
||||
|
||||
updatePinAssignmentsGridEditors();
|
||||
|
||||
// TODO: Show a preview of the symbol with the pin numbers shown.
|
||||
// TODO: Maybe show a preview of the code for subcircuits and code models.
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsGridEditors()
|
||||
{
|
||||
wxString modelPinChoicesString = "";
|
||||
bool isFirst = true;
|
||||
|
||||
for( unsigned int i = 0; i < getCurModel().Pins().size(); ++i )
|
||||
{
|
||||
const SIM_MODEL::PIN& modelPin = getCurModel().Pins().at( i );
|
||||
int modelPinNumber = static_cast<int>( i + 1 );
|
||||
|
||||
if( modelPin.symbolPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
|
||||
continue;
|
||||
|
||||
if( isFirst )
|
||||
{
|
||||
modelPinChoicesString << getModelPinString( modelPinNumber );
|
||||
isFirst = false;
|
||||
}
|
||||
else
|
||||
modelPinChoicesString << "," << getModelPinString( modelPinNumber );
|
||||
}
|
||||
|
||||
if( !isFirst )
|
||||
modelPinChoicesString << ",";
|
||||
|
||||
modelPinChoicesString << "Not Connected";
|
||||
|
||||
for( int i = 0; i < m_pinAssignmentsGrid->GetNumberRows(); ++i )
|
||||
{
|
||||
wxGridCellChoiceEditor* editor = static_cast<wxGridCellChoiceEditor*>(
|
||||
m_pinAssignmentsGrid->GetCellEditor( i, static_cast<int>( PIN_COLUMN::MODEL ) ) );
|
||||
|
||||
if( !editor )
|
||||
{
|
||||
// Shouldn't happen.
|
||||
wxFAIL_MSG( "Grid cell editor is null" );
|
||||
return;
|
||||
}
|
||||
|
||||
wxString curModelPinString = m_pinAssignmentsGrid->GetCellValue(
|
||||
i, static_cast<int>( PIN_COLUMN::MODEL ) );
|
||||
|
||||
if( curModelPinString == "Not Connected" )
|
||||
editor->SetParameters( modelPinChoicesString );
|
||||
else
|
||||
editor->SetParameters( curModelPinString + "," + modelPinChoicesString );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -295,26 +404,28 @@ wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( const SIM_MODEL::PARAM& a
|
|||
switch( aParam.info.type )
|
||||
{
|
||||
case TYPE::INT:
|
||||
prop = new wxIntProperty( paramDescription );
|
||||
prop = new SIM_PROPERTY( paramDescription,aParam.info.name, *aParam.value,
|
||||
SIM_VALUE_BASE::TYPE::INT );
|
||||
break;
|
||||
|
||||
case TYPE::FLOAT:
|
||||
prop = new wxFloatProperty( paramDescription );
|
||||
prop = new SIM_PROPERTY( paramDescription,aParam.info.name, *aParam.value,
|
||||
SIM_VALUE_BASE::TYPE::FLOAT );
|
||||
break;
|
||||
|
||||
case TYPE::BOOL:
|
||||
prop = new wxBoolProperty( paramDescription );
|
||||
prop = new wxBoolProperty( paramDescription, aParam.info.name );
|
||||
prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true );
|
||||
break;
|
||||
|
||||
default:
|
||||
prop = new wxStringProperty( paramDescription );
|
||||
prop = new wxStringProperty( paramDescription, aParam.info.name );
|
||||
break;
|
||||
}
|
||||
|
||||
prop->SetAttribute( wxPG_ATTR_UNITS, aParam.info.unit );
|
||||
|
||||
// Legacy due to the way we extracted parameters from Ngspice.
|
||||
// Legacy due to the way we extracted the parameters from Ngspice.
|
||||
if( aParam.isOtherVariant )
|
||||
prop->SetCell( 3, aParam.info.defaultValueOfOtherVariant );
|
||||
else
|
||||
|
@ -325,7 +436,7 @@ wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( const SIM_MODEL::PARAM& a
|
|||
switch( aParam.info.type )
|
||||
{
|
||||
case TYPE::BOOL: typeStr = wxString( "Bool" ); break;
|
||||
case TYPE::INT: typeStr = wxString( "Integer" ); break;
|
||||
case TYPE::INT: typeStr = wxString( "Int" ); break;
|
||||
case TYPE::FLOAT: typeStr = wxString( "Float" ); break;
|
||||
case TYPE::COMPLEX: typeStr = wxString( "Complex" ); break;
|
||||
case TYPE::STRING: typeStr = wxString( "String" ); break;
|
||||
|
@ -335,7 +446,178 @@ wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( const SIM_MODEL::PARAM& a
|
|||
case TYPE::COMPLEX_VECTOR: typeStr = wxString( "Complex Vector" ); break;
|
||||
}
|
||||
|
||||
prop->SetCell( static_cast<int>( COLUMN::TYPE ), typeStr );
|
||||
prop->SetCell( static_cast<int>( PARAM_COLUMN::TYPE ), typeStr );
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL& DIALOG_SPICE_MODEL<T>::getCurModel() const
|
||||
{
|
||||
return *m_models.at( static_cast<int>( m_curModelType ) );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
wxString DIALOG_SPICE_MODEL<T>::getSymbolPinString( int symbolPinNumber ) const
|
||||
{
|
||||
wxString name = "";
|
||||
SCH_PIN* symbolPin = m_symbol.GetAllPins().at( symbolPinNumber - 1 );
|
||||
|
||||
if( symbolPin )
|
||||
name = symbolPin->GetShownName();
|
||||
|
||||
LOCALE_IO toggle;
|
||||
|
||||
if( name.IsEmpty() )
|
||||
return wxString::Format( "%d", symbolPinNumber );
|
||||
else
|
||||
return wxString::Format( "%d (%s)", symbolPinNumber, symbolPin->GetShownName() );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
wxString DIALOG_SPICE_MODEL<T>::getModelPinString( int modelPinNumber ) const
|
||||
{
|
||||
const wxString& pinName = getCurModel().Pins().at( modelPinNumber - 1 ).name;
|
||||
|
||||
LOCALE_IO toggle;
|
||||
|
||||
if( pinName.IsEmpty() )
|
||||
return wxString::Format( "%d", modelPinNumber, pinName );
|
||||
else
|
||||
return wxString::Format( "%d (%s)", modelPinNumber, pinName );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
int DIALOG_SPICE_MODEL<T>::getModelPinNumber( const wxString& aModelPinString ) const
|
||||
{
|
||||
if( aModelPinString == "Not Connected" )
|
||||
return SIM_MODEL::PIN::NOT_CONNECTED;
|
||||
|
||||
int length = aModelPinString.Find( " " );
|
||||
|
||||
if( length == wxNOT_FOUND )
|
||||
length = static_cast<int>( aModelPinString.Length() );
|
||||
|
||||
long result = 0;
|
||||
aModelPinString.Mid( 0, length ).ToCLong( &result );
|
||||
|
||||
return static_cast<int>( result );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
|
||||
{
|
||||
SIM_MODEL::DEVICE_TYPE deviceType =
|
||||
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
|
||||
|
||||
m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
|
||||
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
||||
{
|
||||
SIM_MODEL::DEVICE_TYPE deviceType =
|
||||
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
|
||||
wxString typeDescription = m_typeChoice->GetString( m_typeChoice->GetSelection() );
|
||||
|
||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||
{
|
||||
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
|
||||
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
||||
{
|
||||
m_curModelType = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent )
|
||||
{
|
||||
int symbolPinNumber = aEvent.GetRow() + 1;
|
||||
int oldModelPinNumber = getModelPinNumber( aEvent.GetString() );
|
||||
int modelPinNumber = getModelPinNumber(
|
||||
m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() ) );
|
||||
|
||||
if( oldModelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
|
||||
getCurModel().Pins().at( oldModelPinNumber - 1 ).symbolPinNumber =
|
||||
SIM_MODEL::PIN::NOT_CONNECTED;
|
||||
|
||||
if( modelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
|
||||
getCurModel().Pins().at( modelPinNumber - 1 ).symbolPinNumber = symbolPinNumber;
|
||||
|
||||
updatePinAssignmentsGridEditors();
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onPinAssignmentsGridSize( wxSizeEvent& aEvent )
|
||||
{
|
||||
wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinAssignmentsGrid );
|
||||
|
||||
int gridWidth = KIPLATFORM::UI::GetUnobscuredSize( m_pinAssignmentsGrid ).x;
|
||||
m_pinAssignmentsGrid->SetColSize( static_cast<int>( PIN_COLUMN::MODEL ), gridWidth / 2 );
|
||||
m_pinAssignmentsGrid->SetColSize( static_cast<int>( PIN_COLUMN::SYMBOL ), gridWidth / 2 );
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onSelectionChange( wxPropertyGridEvent& aEvent )
|
||||
{
|
||||
// TODO: Activate also when the whole property grid is selected with tab key.
|
||||
|
||||
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
||||
if( !grid )
|
||||
{
|
||||
wxFAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
wxWindow* editorControl = grid->GetEditorControl();
|
||||
if( !editorControl )
|
||||
{
|
||||
wxFAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Without this, the user had to press tab before they could edit the field.
|
||||
editorControl->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
/*template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onPropertyChanged( wxPropertyGridEvent& aEvent )
|
||||
{
|
||||
wxString name = aEvent.GetPropertyName();
|
||||
|
||||
for( SIM_MODEL::PARAM& param : getCurModel().Params() )
|
||||
{
|
||||
if( param.info.name == name )
|
||||
{
|
||||
try
|
||||
{
|
||||
param.value->FromString( m_paramGrid->GetPropertyValueAsString( param.info.name ) );
|
||||
}
|
||||
catch( KI_PARAM_ERROR& e )
|
||||
{
|
||||
DisplayErrorMessage( this, e.What() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -41,7 +41,8 @@ template <typename T>
|
|||
class DIALOG_SPICE_MODEL : public DIALOG_SPICE_MODEL_BASE
|
||||
{
|
||||
public:
|
||||
enum class COLUMN : int { DESCRIPTION = 0, VALUE, UNIT, DEFAULT, TYPE, END_ };
|
||||
enum class PARAM_COLUMN : int { DESCRIPTION, VALUE, UNIT, DEFAULT, TYPE, END_ };
|
||||
enum class PIN_COLUMN : int { SYMBOL, MODEL };
|
||||
|
||||
DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol, std::vector<T>& aSchFields );
|
||||
|
||||
|
@ -49,15 +50,28 @@ private:
|
|||
bool TransferDataFromWindow() override;
|
||||
bool TransferDataToWindow() override;
|
||||
|
||||
void updateModel();
|
||||
void updateWidgets();
|
||||
|
||||
void onDeviceTypeChoice( wxCommandEvent& aEvent ) override;
|
||||
void onTypeChoice( wxCommandEvent& aEvent ) override;
|
||||
void updateModelParamsTab();
|
||||
void updateModelCodeTab();
|
||||
void updatePinAssignmentsTab();
|
||||
void updatePinAssignmentsGridEditors();
|
||||
|
||||
void addParamPropertyIfRelevant( const SIM_MODEL::PARAM& aParam );
|
||||
wxPGProperty* newParamProperty( const SIM_MODEL::PARAM& aParam ) const;
|
||||
|
||||
SIM_MODEL& getCurModel() const;
|
||||
wxString getSymbolPinString( int aSymbolPinNumber ) const;
|
||||
wxString getModelPinString( int aModelPinNumber ) const;
|
||||
int getModelPinNumber( const wxString& aModelPinString ) const;
|
||||
|
||||
void onDeviceTypeChoice( wxCommandEvent& aEvent ) override;
|
||||
void onTypeChoice( wxCommandEvent& aEvent ) override;
|
||||
void onPinAssignmentsGridCellChange( wxGridEvent& aEvent ) override;
|
||||
void onPinAssignmentsGridSize( wxSizeEvent& aEvent ) override;
|
||||
|
||||
virtual void onSelectionChange( wxPropertyGridEvent& aEvent );
|
||||
//void onPropertyChanged( wxPropertyGridEvent& aEvent ) override;
|
||||
|
||||
SCH_SYMBOL& m_symbol;
|
||||
std::vector<T>& m_fields;
|
||||
|
||||
|
@ -65,7 +79,6 @@ private:
|
|||
std::map<SIM_MODEL::DEVICE_TYPE, SIM_MODEL::TYPE> m_curModelTypeOfDeviceType;
|
||||
SIM_MODEL::TYPE m_curModelType = SIM_MODEL::TYPE::NONE;
|
||||
|
||||
wxPropertyGridPage* m_paramGrid;
|
||||
wxPGProperty* m_firstCategory; // Used to add principal parameters to root (any better ideas?)
|
||||
std::unique_ptr<SCINTILLA_TRICKS> m_scintillaTricks;
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
|||
m_staticText124->Wrap( -1 );
|
||||
fgSizer15->Add( m_staticText124, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_staticText125 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, wxT("/home/mikolaj/Downloads/1N4148.lib"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText125 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, wxT("etc/kicad-sim/diodes.lib"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText125->Wrap( -1 );
|
||||
fgSizer15->Add( m_staticText125, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
@ -94,8 +94,10 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
|||
|
||||
bSizer12->Add( fgSizer16, 0, wxEXPAND, 5 );
|
||||
|
||||
m_paramGridMgr = new wxPropertyGridManager(m_parametersPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPGMAN_DEFAULT_STYLE);
|
||||
m_paramGridMgr = new wxPropertyGridManager(m_parametersPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPGMAN_DEFAULT_STYLE|wxPG_SPLITTER_AUTO_CENTER);
|
||||
m_paramGridMgr->SetExtraStyle( wxPG_EX_MODE_BUTTONS|wxPG_EX_NATIVE_DOUBLE_BUFFERING );
|
||||
|
||||
m_paramGrid = m_paramGridMgr->AddPage( wxT("Page"), wxNullBitmap );
|
||||
bSizer12->Add( m_paramGridMgr, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
@ -165,34 +167,34 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
|||
wxBoxSizer* bSizer10;
|
||||
bSizer10 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_pinAssignmentGrid = new WX_GRID( m_pinAssignmentsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_pinAssignmentsGrid = new WX_GRID( m_pinAssignmentsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_pinAssignmentGrid->CreateGrid( 0, 2 );
|
||||
m_pinAssignmentGrid->EnableEditing( true );
|
||||
m_pinAssignmentGrid->EnableGridLines( true );
|
||||
m_pinAssignmentGrid->EnableDragGridSize( false );
|
||||
m_pinAssignmentGrid->SetMargins( 0, 0 );
|
||||
m_pinAssignmentsGrid->CreateGrid( 0, 2 );
|
||||
m_pinAssignmentsGrid->EnableEditing( true );
|
||||
m_pinAssignmentsGrid->EnableGridLines( true );
|
||||
m_pinAssignmentsGrid->EnableDragGridSize( false );
|
||||
m_pinAssignmentsGrid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_pinAssignmentGrid->SetColSize( 0, 160 );
|
||||
m_pinAssignmentGrid->SetColSize( 1, 160 );
|
||||
m_pinAssignmentGrid->EnableDragColMove( false );
|
||||
m_pinAssignmentGrid->EnableDragColSize( true );
|
||||
m_pinAssignmentGrid->SetColLabelValue( 0, wxT("Schematic Pin") );
|
||||
m_pinAssignmentGrid->SetColLabelValue( 1, wxT("Model Pin") );
|
||||
m_pinAssignmentGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
m_pinAssignmentsGrid->SetColSize( 0, 160 );
|
||||
m_pinAssignmentsGrid->SetColSize( 1, 160 );
|
||||
m_pinAssignmentsGrid->EnableDragColMove( false );
|
||||
m_pinAssignmentsGrid->EnableDragColSize( true );
|
||||
m_pinAssignmentsGrid->SetColLabelValue( 0, wxT("Symbol Pin") );
|
||||
m_pinAssignmentsGrid->SetColLabelValue( 1, wxT("Model Pin") );
|
||||
m_pinAssignmentsGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_pinAssignmentGrid->EnableDragRowSize( false );
|
||||
m_pinAssignmentGrid->SetRowLabelSize( 0 );
|
||||
m_pinAssignmentGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
m_pinAssignmentsGrid->EnableDragRowSize( false );
|
||||
m_pinAssignmentsGrid->SetRowLabelSize( 0 );
|
||||
m_pinAssignmentsGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_pinAssignmentGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
bSizer10->Add( m_pinAssignmentGrid, 1, wxALL|wxEXPAND, 5 );
|
||||
m_pinAssignmentsGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
bSizer10->Add( m_pinAssignmentsGrid, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_pinAssignmentsPanel->SetSizer( bSizer10 );
|
||||
|
@ -226,6 +228,9 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
|||
// Connect Events
|
||||
m_deviceTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
|
||||
m_typeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this );
|
||||
m_paramGridMgr->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPropertyChanged ), NULL, this );
|
||||
m_pinAssignmentsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridCellChange ), NULL, this );
|
||||
m_pinAssignmentsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridSize ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE()
|
||||
|
@ -233,5 +238,8 @@ DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE()
|
|||
// Disconnect Events
|
||||
m_deviceTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
|
||||
m_typeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this );
|
||||
m_paramGridMgr->Disconnect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPropertyChanged ), NULL, this );
|
||||
m_pinAssignmentsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridCellChange ), NULL, this );
|
||||
m_pinAssignmentsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridSize ), NULL, this );
|
||||
|
||||
}
|
||||
|
|
|
@ -190,11 +190,11 @@
|
|||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxFlexGridSizer" expanded="0">
|
||||
<object class="wxFlexGridSizer" expanded="1">
|
||||
<property name="cols">3</property>
|
||||
<property name="flexible_direction">wxBOTH</property>
|
||||
<property name="growablecols">1</property>
|
||||
|
@ -497,7 +497,7 @@
|
|||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">/home/mikolaj/Downloads/1N4148.lib</property>
|
||||
<property name="label">etc/kicad-sim/diodes.lib</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
|
@ -1044,13 +1044,20 @@
|
|||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxPGMAN_DEFAULT_STYLE</property>
|
||||
<property name="style">wxPGMAN_DEFAULT_STYLE|wxPG_SPLITTER_AUTO_CENTER</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>
|
||||
<event name="OnPropertyGridChanged">onPropertyChanged</event>
|
||||
<object class="propGridPage" expanded="1">
|
||||
<property name="bitmap"></property>
|
||||
<property name="label">Page</property>
|
||||
<property name="name">m_paramGrid</property>
|
||||
<property name="permission">protected</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -1281,7 +1288,7 @@
|
|||
<property name="close_button">1</property>
|
||||
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="col_label_size"></property>
|
||||
<property name="col_label_values">"Schematic Pin" "Model Pin"</property>
|
||||
<property name="col_label_values">"Symbol Pin" "Model Pin"</property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">2</property>
|
||||
<property name="column_sizes">160,160</property>
|
||||
|
@ -1317,7 +1324,7 @@
|
|||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_pinAssignmentGrid</property>
|
||||
<property name="name">m_pinAssignmentsGrid</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
|
@ -1339,6 +1346,8 @@
|
|||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnGridCellChange">onPinAssignmentsGridCellChange</event>
|
||||
<event name="OnSize">onPinAssignmentsGridSize</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
|
|
@ -62,10 +62,11 @@ class DIALOG_SPICE_MODEL_BASE : public wxDialog
|
|||
wxStaticText* m_staticText8;
|
||||
wxChoice* m_typeChoice;
|
||||
wxPropertyGridManager* m_paramGridMgr;
|
||||
wxPropertyGridPage* m_paramGrid;
|
||||
wxPanel* m_codePanel;
|
||||
wxStyledTextCtrl* m_codePreview;
|
||||
wxPanel* m_pinAssignmentsPanel;
|
||||
WX_GRID* m_pinAssignmentGrid;
|
||||
WX_GRID* m_pinAssignmentsGrid;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxCheckBox* m_excludeSymbol;
|
||||
wxStdDialogButtonSizer* m_sdbSizer1;
|
||||
|
@ -75,6 +76,9 @@ class DIALOG_SPICE_MODEL_BASE : public wxDialog
|
|||
// Virtual event handlers, override them in your derived class
|
||||
virtual void onDeviceTypeChoice( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onTypeChoice( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onPropertyChanged( wxPropertyGridEvent& event ) { event.Skip(); }
|
||||
virtual void onPinAssignmentsGridCellChange( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void onPinAssignmentsGridSize( wxSizeEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
|
|
@ -958,6 +958,17 @@ std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
|
|||
}
|
||||
|
||||
|
||||
std::vector<SCH_PIN*> SCH_SYMBOL::GetAllPins() const
|
||||
{
|
||||
std::vector<SCH_PIN*> pins;
|
||||
|
||||
for( const auto& p : m_pins )
|
||||
pins.push_back( p.get() );
|
||||
|
||||
return pins;
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::SwapData( SCH_ITEM* aItem )
|
||||
{
|
||||
wxCHECK_RET( (aItem != nullptr) && (aItem->Type() == SCH_SYMBOL_T),
|
||||
|
|
|
@ -479,6 +479,14 @@ public:
|
|||
*/
|
||||
std::vector<SCH_PIN*> GetPins( const SCH_SHEET_PATH* aSheet = nullptr ) const;
|
||||
|
||||
/**
|
||||
* Retrieve all SCH_PINs (from all sheets)
|
||||
*
|
||||
* @return a vector of pointers (non-owning) to SCH_PINs
|
||||
*/
|
||||
std::vector<SCH_PIN*> GetAllPins() const;
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<SCH_PIN>>& GetRawPins() { return m_pins; }
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016-2018 CERN
|
||||
* Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
|
@ -58,7 +58,7 @@ public:
|
|||
LTRA,
|
||||
TRANLINE,
|
||||
URC,
|
||||
TRANSLINE,
|
||||
//TRANSLINE,
|
||||
SWITCH,
|
||||
CSWITCH,
|
||||
DIODE,
|
||||
|
@ -95,6 +95,7 @@ public:
|
|||
wxString name;
|
||||
wxString variant1;
|
||||
wxString variant2;
|
||||
std::vector<wxString> pinNames;
|
||||
wxString description;
|
||||
std::vector<SIM_MODEL::PARAM::INFO> modelParams;
|
||||
std::vector<SIM_MODEL::PARAM::INFO> instanceParams;
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
#include <macros.h>
|
||||
|
||||
// This script was originally autogenerated using an ugly Bash script, but later modified manually.
|
||||
// Search the Git history if you want to use it to add new models (but don't use it to regenerate
|
||||
// the current ones).
|
||||
// Search the Git history if you want to use that script to add new models, but don't use it to
|
||||
// regenerate the current ones.
|
||||
|
||||
// We cannot use designated initializers until we upgrade to C++20 (we're C++17 now),
|
||||
// so we do this instead.
|
||||
|
@ -84,7 +84,7 @@ static auto QOR() { NGSPICE::PARAM_FLAGS p; p.orQuery=true; p.redundant=true; r
|
|||
#define QO() {}
|
||||
#define QOR() {}
|
||||
|
||||
const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
||||
const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( MODEL_TYPE aType )
|
||||
{
|
||||
// To speed up builds a switch statement is used instead of a std::map literal.
|
||||
// NOTE: I'm not sure if that helped at all, so feel free to try to use std::map instead.
|
||||
|
@ -93,15 +93,15 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
default:
|
||||
wxFAIL;
|
||||
KI_FALLTHROUGH;
|
||||
case NGSPICE::MODEL_TYPE::NONE:
|
||||
case NGSPICE::MODEL_TYPE::_ENUM_END:
|
||||
case MODEL_TYPE::NONE:
|
||||
case MODEL_TYPE::_ENUM_END:
|
||||
{
|
||||
static MODEL_INFO model = {};
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::RESISTOR:
|
||||
case MODEL_TYPE::RESISTOR:
|
||||
{
|
||||
static MODEL_INFO model = { "Resistor", "R", "", "Simple linear resistor",
|
||||
static MODEL_INFO model = { "Resistor", "R", "", { "+", "-" }, "Simple linear resistor",
|
||||
// Model parameters
|
||||
{
|
||||
{ "rsh", 103, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, Q(), "ohm/m", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "0", "", "Sheet resistance" },
|
||||
|
@ -157,9 +157,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::CAPACITOR:
|
||||
case MODEL_TYPE::CAPACITOR:
|
||||
{
|
||||
static MODEL_INFO model = { "Capacitor", "C", "", "Fixed capacitor",
|
||||
static MODEL_INFO model = { "Capacitor", "C", "", { "+", "-" }, "Fixed capacitor",
|
||||
// Model parameters
|
||||
{
|
||||
{ "cap", 113, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Model capacitance" },
|
||||
|
@ -209,9 +209,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::INDUCTOR:
|
||||
case MODEL_TYPE::INDUCTOR:
|
||||
{
|
||||
static MODEL_INFO model = { "Inductor", "L", "", "Fixed inductor",
|
||||
static MODEL_INFO model = { "Inductor", "L", "", { "+", "-" }, "Fixed inductor",
|
||||
// Model parameters
|
||||
{
|
||||
{ "ind", 100, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "H", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Model inductance" },
|
||||
|
@ -249,9 +249,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::LTRA:
|
||||
case MODEL_TYPE::LTRA:
|
||||
{
|
||||
static MODEL_INFO model = { "LTRA", "LTRA", "", "Lossy transmission line",
|
||||
static MODEL_INFO model = { "LTRA", "LTRA", "", { "1+", "1-", "2+", "2-" }, "Lossy transmission line",
|
||||
// Model parameters
|
||||
{
|
||||
{ "ltra", 0, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::BOOL, {}, "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "1", "", "LTRA model" },
|
||||
|
@ -287,9 +287,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::TRANLINE:
|
||||
case MODEL_TYPE::TRANLINE:
|
||||
{
|
||||
static MODEL_INFO model = { "Tranline", "", "", "Lossless transmission line",
|
||||
static MODEL_INFO model = { "Tranline", "", "", { "1+", "1-", "2+", "2-" }, "Lossless transmission line",
|
||||
// Model parameters
|
||||
{
|
||||
},
|
||||
|
@ -315,9 +315,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::URC:
|
||||
case MODEL_TYPE::URC:
|
||||
{
|
||||
static MODEL_INFO model = { "URC", "URC", "", "Uniform R.C. line",
|
||||
static MODEL_INFO model = { "URC", "URC", "", { "1+", "2+", "-" }, "Uniform R.C. line",
|
||||
// Model parameters
|
||||
{
|
||||
{ "k", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::PRINCIPAL, "1.5", "", "Propagation constant" },
|
||||
|
@ -338,9 +338,10 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::TRANSLINE:
|
||||
/*case MODEL_TYPE::TRANSLINE:
|
||||
{
|
||||
static MODEL_INFO model = { "TransLine", "", "", "Simple Lossy Transmission Line",
|
||||
// FIXME: Second and fourth pins should be set to zero.
|
||||
static MODEL_INFO model = { "TransLine", "", "", { "1+", "0", "2+", "0" }, "Simple Lossy Transmission Line",
|
||||
// Model parameters
|
||||
{
|
||||
{ "r", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "ohm/m", SIM_MODEL::PARAM::CATEGORY::DISTRIBUTED_QUANTITIES, "", "", "resistance per length" },
|
||||
|
@ -357,10 +358,10 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
{ "length", 3, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "m", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "", "", "length of line" },
|
||||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::SWITCH:
|
||||
}*/
|
||||
case MODEL_TYPE::SWITCH:
|
||||
{
|
||||
static MODEL_INFO model = { "Switch", "SW", "", "Ideal voltage controlled switch",
|
||||
static MODEL_INFO model = { "Switch", "SW", "", { "+", "-", "Ctrl+", "Ctrl-" }, "Ideal voltage controlled switch",
|
||||
// Model parameters
|
||||
{
|
||||
{ "sw", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::BOOL, U(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "NaN", "", "Switch model" },
|
||||
|
@ -384,9 +385,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::CSWITCH:
|
||||
case MODEL_TYPE::CSWITCH:
|
||||
{
|
||||
static MODEL_INFO model = { "CSwitch", "CSW", "", "Current controlled ideal switch",
|
||||
static MODEL_INFO model = { "CSwitch", "CSW", "", { "+", "-", "Ctrl+", "Ctrl-" }, "Current controlled ideal switch",
|
||||
// Model parameters
|
||||
{
|
||||
{ "csw", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::BOOL, U(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "NaN", "", "Current controlled switch model" },
|
||||
|
@ -409,9 +410,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::DIODE:
|
||||
case MODEL_TYPE::DIODE:
|
||||
{
|
||||
static MODEL_INFO model = { "Diode", "D", "", "Junction Diode model",
|
||||
static MODEL_INFO model = { "Diode", "D", "", { "Anode", "Cathode" }, "Junction Diode model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "level", 100, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "1", "", "Diode level selector" },
|
||||
|
@ -429,7 +430,7 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
{ "tt", 104, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "s", SIM_MODEL::PARAM::CATEGORY::DC, "0", "", "Transit Time" },
|
||||
{ "ttt1", 125, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "s", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "Transit Time 1st order temp. coeff." },
|
||||
{ "ttt2", 126, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "s", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "Transit Time 2nd order temp. coeff." },
|
||||
{ "cjo", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::DC, "0", "", "Junction capacitance" },
|
||||
{ "cjo", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, A(), "F", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "0", "", "Junction capacitance" },
|
||||
{ "cj0", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, AR(), "F", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Junction capacitance" },
|
||||
{ "cj", 105, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, AR(), "F", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "Junction capacitance" },
|
||||
{ "vj", 106, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "V", SIM_MODEL::PARAM::CATEGORY::DC, "1", "", "Junction potential" },
|
||||
|
@ -438,7 +439,7 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
{ "mj", 107, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, R(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0.5", "", "n.a." },
|
||||
{ "tm1", 127, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "1/deg C^2", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "Grading coefficient 1st temp. coeff." },
|
||||
{ "tm2", 128, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "1/deg C", SIM_MODEL::PARAM::CATEGORY::TEMPERATURE, "0", "", "Grading coefficient 2nd temp. coeff." },
|
||||
{ "cjp", 119, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "F", SIM_MODEL::PARAM::CATEGORY::DC, "0", "", "Sidewall junction capacitance" },
|
||||
{ "cjp", 119, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "F", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "0", "", "Sidewall junction capacitance" },
|
||||
{ "cjsw", 119, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, R(), "", SIM_MODEL::PARAM::CATEGORY::SUPERFLUOUS, "0", "", "n.a." },
|
||||
{ "php", 120, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "V", SIM_MODEL::PARAM::CATEGORY::DC, "1", "", "Sidewall junction potential" },
|
||||
{ "mjsw", 121, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "0.33", "", "Sidewall Grading coefficient" },
|
||||
|
@ -526,9 +527,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::BJT:
|
||||
case MODEL_TYPE::BJT:
|
||||
{
|
||||
static MODEL_INFO model = { "BJT", "NPN", "PNP", "Bipolar Junction Transistor",
|
||||
static MODEL_INFO model = { "BJT", "NPN", "PNP", { "Collector", "Base", "Emitter" }, "Bipolar Junction Transistor",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 309, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "npn", "pnp", "NPN or PNP" },
|
||||
|
@ -742,9 +743,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::VBIC:
|
||||
case MODEL_TYPE::VBIC:
|
||||
{
|
||||
static MODEL_INFO model = { "VBIC", "NPN", "PNP", "Vertical Bipolar Inter-Company Model",
|
||||
static MODEL_INFO model = { "VBIC", "NPN", "PNP", { "Collector", "Base", "Emitter" }, "Vertical Bipolar Inter-Company Model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 305, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "npn", "pnp", "NPN or PNP" },
|
||||
|
@ -915,9 +916,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::HICUM2:
|
||||
case MODEL_TYPE::HICUM2:
|
||||
{
|
||||
static MODEL_INFO model = { "hicum2", "NPN", "PNP", "High Current Model for BJT",
|
||||
static MODEL_INFO model = { "hicum2", "NPN", "PNP", { "Collector", "Base", "Emitter" }, "High Current Model for BJT",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 305, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "npn", "pnp", "For transistor type NPN(+1) or PNP (-1)" },
|
||||
|
@ -1136,9 +1137,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::JFET:
|
||||
case MODEL_TYPE::JFET:
|
||||
{
|
||||
static MODEL_INFO model = { "JFET", "NJF", "PJF", "Junction Field effect transistor",
|
||||
static MODEL_INFO model = { "JFET", "NJF", "PJF", { "Drain", "Gate", "Source" }, "Junction Field effect transistor",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 305, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "njf", "pjf", "N-type or P-type JFET model" },
|
||||
|
@ -1203,9 +1204,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::JFET2:
|
||||
case MODEL_TYPE::JFET2:
|
||||
{
|
||||
static MODEL_INFO model = { "JFET2", "NJF", "PJF", "Short channel field effect transistor",
|
||||
static MODEL_INFO model = { "JFET2", "NJF", "PJF", { "Drain", "Gate", "Source" }, "Short channel field effect transistor",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 305, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "njf", "pjf", "N-type or P-type JFET2 model" },
|
||||
|
@ -1283,9 +1284,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MES:
|
||||
case MODEL_TYPE::MES:
|
||||
{
|
||||
static MODEL_INFO model = { "MES", "NMF", "PMF", "GaAs MESFET model",
|
||||
static MODEL_INFO model = { "MES", "NMF", "PMF", { "Drain", "Gate", "Source" }, "GaAs MESFET model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 305, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::BOOL, {}, "", SIM_MODEL::PARAM::CATEGORY::FLAGS, "-693161728", "116101380", "N-type or P-type MESfet model" },
|
||||
|
@ -1341,9 +1342,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MESA:
|
||||
case MODEL_TYPE::MESA:
|
||||
{
|
||||
static MODEL_INFO model = { "MESA", "NMF", "PMF", "GaAs MESFET model",
|
||||
static MODEL_INFO model = { "MESA", "NMF", "PMF", { "Drain", "Gate", "Source" }, "GaAs MESFET model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 165, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nmf", "nmf", "N-type or P-type MESfet model" },
|
||||
|
@ -1433,9 +1434,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::HFET1:
|
||||
case MODEL_TYPE::HFET1:
|
||||
{
|
||||
static MODEL_INFO model = { "HFET1", "NMF", "PMF", "HFET1 Model",
|
||||
static MODEL_INFO model = { "HFET1", "NMF", "PMF", { "Drain", "Gate", "Source", "Bulk" }, "HFET1 Model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "vt0", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "V", SIM_MODEL::PARAM::CATEGORY::DC, "0.15", "0.15", "Pinch-off voltage" },
|
||||
|
@ -1494,9 +1495,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::HFET2:
|
||||
case MODEL_TYPE::HFET2:
|
||||
{
|
||||
static MODEL_INFO model = { "HFET2", "NMF", "PMF", "HFET2 Model",
|
||||
static MODEL_INFO model = { "HFET2", "NMF", "PMF", { "Drain", "Gate", "Source", "Bulk" }, "HFET2 Model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 139, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nhfet", "nhfet", "NHFET or PHFET" },
|
||||
|
@ -1552,9 +1553,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MOS1:
|
||||
case MODEL_TYPE::MOS1:
|
||||
{
|
||||
static MODEL_INFO model = { "Mos1", "NMOS", "PMOS", "Level 1 MOSfet model with Meyer capacitance model",
|
||||
static MODEL_INFO model = { "Mos1", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Level 1 MOSfet model with Meyer capacitance model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 133, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nmos", "pmos", "N-channel or P-channel MOS" },
|
||||
|
@ -1674,9 +1675,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MOS2:
|
||||
case MODEL_TYPE::MOS2:
|
||||
{
|
||||
static MODEL_INFO model = { "Mos2", "NMOS", "PMOS", "Level 2 MOSfet model with Meyer capacitance model",
|
||||
static MODEL_INFO model = { "Mos2", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Level 2 MOSfet model with Meyer capacitance model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 141, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nmos", "pmos", "N-channel or P-channel MOS" },
|
||||
|
@ -1803,9 +1804,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MOS3:
|
||||
case MODEL_TYPE::MOS3:
|
||||
{
|
||||
static MODEL_INFO model = { "Mos3", "NMOS", "PMOS", "Level 3 MOSfet model with Meyer capacitance model",
|
||||
static MODEL_INFO model = { "Mos3", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Level 3 MOSfet model with Meyer capacitance model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 144, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nmos", "pmos", "N-channel or P-channel MOS" },
|
||||
|
@ -1943,9 +1944,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::BSIM1:
|
||||
case MODEL_TYPE::BSIM1:
|
||||
{
|
||||
static MODEL_INFO model = { "BSIM1", "NMOS", "PMOS", "Berkeley Short Channel IGFET Model",
|
||||
static MODEL_INFO model = { "BSIM1", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley Short Channel IGFET Model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "vfb", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "V", SIM_MODEL::PARAM::CATEGORY::DC, "0", "0", "Flat band voltage" },
|
||||
|
@ -2049,9 +2050,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::BSIM2:
|
||||
case MODEL_TYPE::BSIM2:
|
||||
{
|
||||
static MODEL_INFO model = { "BSIM2", "NMOS", "PMOS", "Berkeley Short Channel IGFET Model",
|
||||
static MODEL_INFO model = { "BSIM2", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley Short Channel IGFET Model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "vfb", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::FLOAT, {}, "V", SIM_MODEL::PARAM::CATEGORY::DC, "-1", "-1", "Flat band voltage" },
|
||||
|
@ -2211,9 +2212,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MOS6:
|
||||
case MODEL_TYPE::MOS6:
|
||||
{
|
||||
static MODEL_INFO model = { "Mos6", "NMOS", "PMOS", "Level 6 MOSfet model with Meyer capacitance model",
|
||||
static MODEL_INFO model = { "Mos6", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Level 6 MOSfet model with Meyer capacitance model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 140, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nmos", "pmos", "N-channel or P-channel MOS" },
|
||||
|
@ -2342,9 +2343,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::BSIM3:
|
||||
case MODEL_TYPE::BSIM3:
|
||||
{
|
||||
static MODEL_INFO model = { "BSIM3", "NMOS", "PMOS", "Berkeley Short Channel IGFET Model Version-3",
|
||||
static MODEL_INFO model = { "BSIM3", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley Short Channel IGFET Model Version-3",
|
||||
// Model parameters
|
||||
{
|
||||
{ "capmod", 100, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "3", "3", "Capacitance model selector" },
|
||||
|
@ -2828,9 +2829,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::MOS9:
|
||||
case MODEL_TYPE::MOS9:
|
||||
{
|
||||
static MODEL_INFO model = { "Mos9", "NMOS", "PMOS", "Modified Level 3 MOSfet model",
|
||||
static MODEL_INFO model = { "Mos9", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Modified Level 3 MOSfet model",
|
||||
// Model parameters
|
||||
{
|
||||
{ "type", 144, SIM_MODEL::PARAM::DIR::OUT, SIM_VALUE_BASE::TYPE::STRING, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "nmos", "pmos", "N-channel or P-channel MOS" },
|
||||
|
@ -2968,9 +2969,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::B4SOI:
|
||||
case MODEL_TYPE::B4SOI:
|
||||
{
|
||||
static MODEL_INFO model = { "B4SOI", "NMOS", "PMOS", "Berkeley SOI MOSFET model version 4.4.0",
|
||||
static MODEL_INFO model = { "B4SOI", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley SOI MOSFET model version 4.4.0",
|
||||
// Model parameters
|
||||
{
|
||||
{ "mtrlmod", 100, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "0", "0", "parameter for non-silicon substrate or metal gate selector" },
|
||||
|
@ -3968,9 +3969,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::BSIM4:
|
||||
case MODEL_TYPE::BSIM4:
|
||||
{
|
||||
static MODEL_INFO model = { "BSIM4", "NMOS", "PMOS", "Berkeley Short Channel IGFET Model-4",
|
||||
static MODEL_INFO model = { "BSIM4", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley Short Channel IGFET Model-4",
|
||||
// Model parameters
|
||||
{
|
||||
{ "cvchargemod", 76, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "0", "0", "Capacitance Charge model selector" },
|
||||
|
@ -4955,9 +4956,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::B3SOIFD:
|
||||
case MODEL_TYPE::B3SOIFD:
|
||||
{
|
||||
static MODEL_INFO model = { "B3SOIFD", "NMOS", "PMOS", "Berkeley SOI MOSFET (FD) model version 2.1",
|
||||
static MODEL_INFO model = { "B3SOIFD", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley SOI MOSFET (FD) model version 2.1",
|
||||
// Model parameters
|
||||
{
|
||||
{ "capmod", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "2", "2", "Capacitance model selector" },
|
||||
|
@ -5386,9 +5387,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::B3SOIDD:
|
||||
case MODEL_TYPE::B3SOIDD:
|
||||
{
|
||||
static MODEL_INFO model = { "B3SOIDD", "NMOS", "PMOS", "Berkeley SOI MOSFET (DD) model version 2.1",
|
||||
static MODEL_INFO model = { "B3SOIDD", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley SOI MOSFET (DD) model version 2.1",
|
||||
// Model parameters
|
||||
{
|
||||
{ "capmod", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "2", "2", "Capacitance model selector" },
|
||||
|
@ -5817,9 +5818,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::B3SOIPD:
|
||||
case MODEL_TYPE::B3SOIPD:
|
||||
{
|
||||
static MODEL_INFO model = { "B3SOIPD", "NMOS", "PMOS", "Berkeley SOI (PD) MOSFET model version 2.2.3",
|
||||
static MODEL_INFO model = { "B3SOIPD", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Berkeley SOI (PD) MOSFET model version 2.2.3",
|
||||
// Model parameters
|
||||
{
|
||||
{ "capmod", 101, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::CAPACITANCE, "2", "2", "Capacitance model selector" },
|
||||
|
@ -6334,9 +6335,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::HISIM2:
|
||||
case MODEL_TYPE::HISIM2:
|
||||
{
|
||||
static MODEL_INFO model = { "HiSIM2", "NMOS", "PMOS", "Hiroshima University STARC IGFET Model 2.8.0",
|
||||
static MODEL_INFO model = { "HiSIM2", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Hiroshima University STARC IGFET Model 2.8.0",
|
||||
// Model parameters
|
||||
{
|
||||
{ "info", 4, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "0", "0", "information level (for debug, etc.)" },
|
||||
|
@ -6890,9 +6891,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::HISIMHV1:
|
||||
case MODEL_TYPE::HISIMHV1:
|
||||
{
|
||||
static MODEL_INFO model = { "HiSIMHV1", "NMOS", "PMOS", "Hiroshima University STARC IGFET Model - HiSIM_HV v.1",
|
||||
static MODEL_INFO model = { "HiSIMHV1", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Hiroshima University STARC IGFET Model - HiSIM_HV v.1",
|
||||
// Model parameters
|
||||
{
|
||||
{ "info", 4, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "0", "0", "Information level (for debug, etc.)" },
|
||||
|
@ -7503,9 +7504,9 @@ const NGSPICE::MODEL_INFO& NGSPICE::ModelInfo( NGSPICE::MODEL_TYPE aType )
|
|||
} };
|
||||
return model;
|
||||
}
|
||||
case NGSPICE::MODEL_TYPE::HISIMHV2:
|
||||
case MODEL_TYPE::HISIMHV2:
|
||||
{
|
||||
static MODEL_INFO model = { "HiSIMHV2", "NMOS", "PMOS", "Hiroshima University STARC IGFET Model - HiSIM_HV v.2",
|
||||
static MODEL_INFO model = { "HiSIMHV2", "NMOS", "PMOS", { "Drain", "Gate", "Source", "Bulk" }, "Hiroshima University STARC IGFET Model - HiSIM_HV v.2",
|
||||
// Model parameters
|
||||
{
|
||||
{ "info", 4, SIM_MODEL::PARAM::DIR::INOUT, SIM_VALUE_BASE::TYPE::INT, {}, "", SIM_MODEL::PARAM::CATEGORY::DC, "0", "0", "Information level (for debug, etc.)" },
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,13 +25,13 @@
|
|||
#ifndef SIM_MODEL_H
|
||||
#define SIM_MODEL_H
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <enum_vector.h>
|
||||
#include <sch_field.h>
|
||||
#include <lib_field.h>
|
||||
#include <sim/sim_value.h>
|
||||
#include <wx/string.h>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
class SIM_MODEL
|
||||
|
@ -40,6 +40,7 @@ public:
|
|||
static constexpr auto DEVICE_TYPE_FIELD = "Model_Device";
|
||||
static constexpr auto TYPE_FIELD = "Model_Type";
|
||||
static constexpr auto FILE_FIELD = "Model_File";
|
||||
static constexpr auto PIN_SEQUENCE_FIELD = "Model_Pin_Sequence";
|
||||
static constexpr auto PARAMS_FIELD = "Model_Params";
|
||||
|
||||
|
||||
|
@ -237,6 +238,15 @@ public:
|
|||
};
|
||||
|
||||
|
||||
struct PIN
|
||||
{
|
||||
static constexpr auto NOT_CONNECTED = 0;
|
||||
|
||||
int symbolPinNumber;
|
||||
const wxString name;
|
||||
};
|
||||
|
||||
|
||||
struct PARAM
|
||||
{
|
||||
enum class DIR
|
||||
|
@ -290,16 +300,19 @@ public:
|
|||
|
||||
|
||||
static DEVICE_INFO DeviceTypeInfo( DEVICE_TYPE aDeviceType );
|
||||
|
||||
static INFO TypeInfo( TYPE aType );
|
||||
|
||||
template <typename T>
|
||||
static TYPE ReadTypeFromFields( const std::vector<T>& aFields );
|
||||
|
||||
template <typename T>
|
||||
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields );
|
||||
|
||||
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
|
||||
template <typename T>
|
||||
static std::unique_ptr<SIM_MODEL> Create( int symbolPinCount, const std::vector<T>& aFields );
|
||||
|
||||
template <typename T = void>
|
||||
static std::unique_ptr<SIM_MODEL> Create( TYPE aType,
|
||||
int symbolPinCount,
|
||||
const std::vector<T>* aFields = nullptr );
|
||||
|
||||
|
||||
// Move semantics.
|
||||
|
@ -312,40 +325,59 @@ public:
|
|||
|
||||
SIM_MODEL( TYPE aType );
|
||||
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL( const std::vector<T>& aFields );
|
||||
void ReadDataFields( int symbolPinCount, const std::vector<T>* aFields );
|
||||
|
||||
// C++ doesn't allow virtual template methods, so we do this:
|
||||
virtual void ReadDataSchFields( int symbolPinCount, const std::vector<SCH_FIELD>* aFields );
|
||||
virtual void ReadDataLibFields( int symbolPinCount, const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
|
||||
template <typename T>
|
||||
void WriteFields( std::vector<T>& aFields );
|
||||
|
||||
// C++ doesn't allow virtual template methods, so we do this:
|
||||
virtual void DoWriteSchFields( std::vector<SCH_FIELD>& aFields );
|
||||
virtual void DoWriteLibFields( std::vector<LIB_FIELD>& aFields );
|
||||
virtual void WriteDataSchFields( std::vector<SCH_FIELD>& aFields );
|
||||
virtual void WriteDataLibFields( std::vector<LIB_FIELD>& aFields );
|
||||
|
||||
virtual void WriteCode( wxString& aCode ) = 0;
|
||||
|
||||
|
||||
TYPE GetType() { return m_type; }
|
||||
|
||||
wxString GetFile() { return m_file; }
|
||||
void SetFile( const wxString& aFile ) { m_file = aFile; }
|
||||
virtual wxString GetFile() { return m_file; }
|
||||
virtual void SetFile( const wxString& aFile ) { m_file = aFile; }
|
||||
|
||||
std::vector<PIN>& Pins() { return m_pins; }
|
||||
std::vector<PARAM>& Params() { return m_params; }
|
||||
|
||||
|
||||
private:
|
||||
TYPE m_type;
|
||||
wxString m_file;
|
||||
std::vector<PIN> m_pins;
|
||||
std::vector<PARAM> m_params;
|
||||
|
||||
|
||||
template <typename T>
|
||||
static wxString getFieldValue( const std::vector<T>& aFields, const wxString& aFieldName );
|
||||
void doReadDataFields( int symbolPinCount, const std::vector<T>* aFields );
|
||||
|
||||
template <typename T>
|
||||
void doWriteFields( std::vector<T>& aFields );
|
||||
|
||||
|
||||
template <typename T>
|
||||
static wxString getFieldValue( const std::vector<T>* aFields, const wxString& aFieldName );
|
||||
|
||||
template <typename T>
|
||||
static void setFieldValue( std::vector<T>& aFields, const wxString& aFieldName,
|
||||
const wxString& aValue );
|
||||
|
||||
virtual std::vector<wxString> getPinNames() { return {}; }
|
||||
|
||||
wxString generatePinSequence();
|
||||
void parsePinSequence( int symbolPinCount, const wxString& aPinSequence );
|
||||
|
||||
virtual wxString generateParamValuePairs();
|
||||
virtual void parseParamValuePairs( const wxString& aParamValuePairs );
|
||||
|
|
|
@ -24,7 +24,18 @@
|
|||
|
||||
#include <sim/sim_model_behavioral.h>
|
||||
|
||||
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) : SIM_MODEL( aType )
|
||||
|
||||
template SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
static PARAM::INFO resistor = makeParamInfo( "r", "Expression for resistance", "ohm" );
|
||||
static PARAM::INFO capacitor = makeParamInfo( "c", "Expression for capacitance", "F" );
|
||||
|
@ -42,6 +53,8 @@ SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) : SIM_MODEL( aType )
|
|||
default:
|
||||
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" );
|
||||
}
|
||||
|
||||
ReadDataFields( symbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
class SIM_MODEL_BEHAVIORAL : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_BEHAVIORAL( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
|
||||
|
|
|
@ -24,7 +24,18 @@
|
|||
|
||||
#include <sim/sim_model_codemodel.h>
|
||||
|
||||
SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType ) : SIM_MODEL( aType )
|
||||
|
||||
template SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
class SIM_MODEL_CODEMODEL : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_CODEMODEL( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
};
|
||||
|
|
|
@ -27,7 +27,17 @@
|
|||
using PARAM = SIM_MODEL::PARAM;
|
||||
|
||||
|
||||
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) : SIM_MODEL( aType )
|
||||
template SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "ohm" );
|
||||
static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" );
|
||||
|
@ -41,6 +51,8 @@ SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) : SIM_MODEL( aType )
|
|||
default:
|
||||
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" );
|
||||
}
|
||||
|
||||
ReadDataFields( symbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,6 +62,12 @@ void SIM_MODEL_IDEAL::WriteCode( wxString& aCode )
|
|||
}
|
||||
|
||||
|
||||
std::vector<wxString> SIM_MODEL_IDEAL::getPinNames()
|
||||
{
|
||||
return { "+", "-" };
|
||||
}
|
||||
|
||||
|
||||
PARAM::INFO SIM_MODEL_IDEAL::makeParamInfo( wxString aName, wxString aDescription, wxString aUnit )
|
||||
{
|
||||
SIM_MODEL::PARAM::INFO paramInfo = {};
|
||||
|
|
|
@ -31,11 +31,14 @@
|
|||
class SIM_MODEL_IDEAL : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_IDEAL( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
|
||||
private:
|
||||
std::vector<wxString> getPinNames() override;
|
||||
|
||||
static PARAM::INFO makeParamInfo( wxString aName, wxString aDescription, wxString aUnit );
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,17 @@
|
|||
using TYPE = SIM_MODEL::TYPE;
|
||||
|
||||
|
||||
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) : SIM_MODEL( aType )
|
||||
template SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
const NGSPICE::MODEL_INFO& modelInfo = NGSPICE::ModelInfo( getModelType() );
|
||||
|
||||
|
@ -42,6 +52,8 @@ SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) : SIM_MODEL( aType )
|
|||
Params().emplace_back( paramInfo );
|
||||
Params().back().isOtherVariant = getIsOtherVariant();
|
||||
}
|
||||
|
||||
ReadDataFields( symbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,6 +63,12 @@ void SIM_MODEL_NGSPICE::WriteCode( wxString& aCode )
|
|||
}
|
||||
|
||||
|
||||
std::vector<wxString> SIM_MODEL_NGSPICE::getPinNames()
|
||||
{
|
||||
return NGSPICE::ModelInfo( getModelType() ).pinNames;
|
||||
}
|
||||
|
||||
|
||||
NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType()
|
||||
{
|
||||
switch( GetType() )
|
||||
|
@ -62,7 +80,7 @@ NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType()
|
|||
case TYPE::TLINE_LOSSY: return NGSPICE::MODEL_TYPE::LTRA;
|
||||
case TYPE::TLINE_LOSSLESS: return NGSPICE::MODEL_TYPE::TRANLINE;
|
||||
case TYPE::TLINE_UNIFORM_RC: return NGSPICE::MODEL_TYPE::URC;
|
||||
case TYPE::TLINE_KSPICE: return NGSPICE::MODEL_TYPE::TRANSLINE;
|
||||
//case TYPE::TLINE_KSPICE: return NGSPICE::MODEL_TYPE::TRANSLINE;
|
||||
case TYPE::SWITCH_VCTRL: return NGSPICE::MODEL_TYPE::SWITCH;
|
||||
case TYPE::SWITCH_ICTRL: return NGSPICE::MODEL_TYPE::CSWITCH;
|
||||
case TYPE::DIODE: return NGSPICE::MODEL_TYPE::DIODE;
|
||||
|
|
|
@ -32,11 +32,14 @@
|
|||
class SIM_MODEL_NGSPICE : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_NGSPICE( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
|
||||
private:
|
||||
std::vector<wxString> getPinNames() override;
|
||||
|
||||
NGSPICE::MODEL_TYPE getModelType();
|
||||
bool getIsOtherVariant();
|
||||
};
|
||||
|
|
|
@ -25,8 +25,19 @@
|
|||
#include <sim/sim_model_rawspice.h>
|
||||
|
||||
|
||||
SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType ) : SIM_MODEL( aType )
|
||||
template SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
ReadDataFields( symbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
class SIM_MODEL_RAWSPICE : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_RAWSPICE( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
};
|
||||
|
|
|
@ -27,10 +27,21 @@
|
|||
using PARAM = SIM_MODEL::PARAM;
|
||||
|
||||
|
||||
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) : SIM_MODEL( aType )
|
||||
template SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
for( const PARAM::INFO& paramInfo : makeParams( aType ) )
|
||||
Params().emplace_back( paramInfo );
|
||||
|
||||
ReadDataFields( symbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
|
@ -480,12 +491,12 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeWhiteNoise( wxString aPrefix, wxS
|
|||
paramInfo.description = "White noise RMS amplitude";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "rtsam";
|
||||
paramInfo.name = "nt";
|
||||
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.unit = "s";
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Burst noise amplitude";
|
||||
paramInfo.description = "Time step";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
return paramInfos;
|
||||
|
@ -497,6 +508,14 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePinkNoise( wxString aPrefix, wxSt
|
|||
std::vector<PARAM::INFO> paramInfos;
|
||||
PARAM::INFO paramInfo;
|
||||
|
||||
paramInfo.name = aPrefix + "o";
|
||||
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "";
|
||||
paramInfo.description = "DC offset";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "nalpha";
|
||||
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
|
||||
paramInfo.unit = "";
|
||||
|
@ -530,6 +549,14 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeBurstNoise( wxString aPrefix, wxS
|
|||
std::vector<PARAM::INFO> paramInfos;
|
||||
PARAM::INFO paramInfo;
|
||||
|
||||
paramInfo.name = "rtsam";
|
||||
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Burst noise amplitude";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "rtscapt";
|
||||
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
|
||||
paramInfo.unit = "s";
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
class SIM_MODEL_SOURCE : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_SOURCE( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
|
||||
|
|
|
@ -24,8 +24,20 @@
|
|||
|
||||
#include <sim/sim_model_subcircuit.h>
|
||||
|
||||
SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType ) : SIM_MODEL( aType )
|
||||
|
||||
template SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
|
||||
const std::vector<void>* aFields );
|
||||
template SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
template SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
|
||||
template <typename T>
|
||||
SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
ReadDataFields( symbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
class SIM_MODEL_SUBCIRCUIT : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_SUBCIRCUIT( TYPE aType );
|
||||
template <typename T = void>
|
||||
SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
|
||||
|
||||
void WriteCode( wxString& aCode ) override;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mikolaj Wielgus
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* https://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <sim/sim_property.h>
|
||||
#include <sim/sim_value.h>
|
||||
#include <ki_exception.h>
|
||||
#include <confirm.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/combobox.h>
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( SIM_VALIDATOR, wxValidator )
|
||||
EVT_TEXT( wxID_ANY, SIM_VALIDATOR::onText )
|
||||
EVT_CHAR( SIM_VALIDATOR::onChar )
|
||||
EVT_MOUSE_EVENTS( SIM_VALIDATOR::onMouse )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
SIM_VALIDATOR::SIM_VALIDATOR( SIM_VALUE_BASE::TYPE aValueType,
|
||||
SIM_VALUE_PARSER::NOTATION aNotation )
|
||||
: wxValidator(),
|
||||
m_valueType( aValueType ),
|
||||
m_notation( aNotation )
|
||||
{
|
||||
wxTextEntry* textEntry = getTextEntry();
|
||||
if( !textEntry )
|
||||
return;
|
||||
|
||||
m_prevText = textEntry->GetValue();
|
||||
m_prevInsertionPoint = textEntry->GetInsertionPoint();
|
||||
}
|
||||
|
||||
|
||||
wxObject* SIM_VALIDATOR::Clone() const
|
||||
{
|
||||
return new SIM_VALIDATOR( *this );
|
||||
}
|
||||
|
||||
|
||||
bool SIM_VALIDATOR::Validate( wxWindow* aParent )
|
||||
{
|
||||
if( !m_validatorWindow->IsEnabled() )
|
||||
return true;
|
||||
|
||||
wxTextEntry* const textEntry = getTextEntry();
|
||||
if( !textEntry )
|
||||
return false;
|
||||
|
||||
return isValid( textEntry->GetValue() );
|
||||
}
|
||||
|
||||
|
||||
bool SIM_VALIDATOR::TransferToWindow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SIM_VALIDATOR::TransferFromWindow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SIM_VALIDATOR::isValid( const wxString& aString )
|
||||
{
|
||||
return SIM_VALUE_PARSER::IsValid( aString, m_valueType, m_notation );
|
||||
}
|
||||
|
||||
|
||||
wxTextEntry* SIM_VALIDATOR::getTextEntry()
|
||||
{
|
||||
// Taken from wxTextValidator.
|
||||
|
||||
if( wxDynamicCast( m_validatorWindow, wxTextCtrl ) )
|
||||
return ( wxTextCtrl* ) m_validatorWindow;
|
||||
|
||||
if( wxDynamicCast( m_validatorWindow, wxComboBox ) )
|
||||
return ( wxComboBox* ) m_validatorWindow;
|
||||
|
||||
if( wxDynamicCast( m_validatorWindow, wxComboCtrl ) )
|
||||
return ( wxComboCtrl* ) m_validatorWindow;
|
||||
|
||||
wxFAIL_MSG(
|
||||
"SIM_VALIDATOR can only be used with wxTextCtrl, wxComboBox, or wxComboCtrl"
|
||||
);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void SIM_VALIDATOR::onText( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxTextEntry* textEntry = getTextEntry();
|
||||
if( !textEntry )
|
||||
return;
|
||||
|
||||
if( !isValid( textEntry->GetValue() ) )
|
||||
{
|
||||
textEntry->ChangeValue( m_prevText );
|
||||
textEntry->SetInsertionPoint( m_prevInsertionPoint );
|
||||
}
|
||||
|
||||
m_prevText = textEntry->GetValue();
|
||||
m_prevInsertionPoint = textEntry->GetInsertionPoint();
|
||||
}
|
||||
|
||||
|
||||
void SIM_VALIDATOR::onChar( wxKeyEvent& aEvent )
|
||||
{
|
||||
aEvent.Skip();
|
||||
|
||||
wxTextEntry* textEntry = getTextEntry();
|
||||
if( !textEntry )
|
||||
return;
|
||||
|
||||
m_prevInsertionPoint = textEntry->GetInsertionPoint();
|
||||
}
|
||||
|
||||
void SIM_VALIDATOR::onMouse( wxMouseEvent& aEvent )
|
||||
{
|
||||
aEvent.Skip();
|
||||
|
||||
wxTextEntry* textEntry = getTextEntry();
|
||||
if( !textEntry )
|
||||
return;
|
||||
|
||||
m_prevInsertionPoint = textEntry->GetInsertionPoint();
|
||||
}
|
||||
|
||||
|
||||
SIM_PROPERTY::SIM_PROPERTY( const wxString& aLabel, const wxString& aName,
|
||||
SIM_VALUE_BASE& aValue,
|
||||
SIM_VALUE_BASE::TYPE aValueType,
|
||||
SIM_VALUE_PARSER::NOTATION aNotation )
|
||||
: wxStringProperty( aLabel, aName, aValue.ToString() ),
|
||||
m_valueType( aValueType ),
|
||||
m_notation( aNotation ),
|
||||
m_value( aValue )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxValidator* SIM_PROPERTY::DoGetValidator() const
|
||||
{
|
||||
return new SIM_VALIDATOR( m_valueType, m_notation );
|
||||
}
|
||||
|
||||
|
||||
bool SIM_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags ) const
|
||||
{
|
||||
try
|
||||
{
|
||||
m_value.FromString( aText );
|
||||
}
|
||||
catch( KI_PARAM_ERROR& e )
|
||||
{
|
||||
aVariant = aText;
|
||||
return false;
|
||||
}
|
||||
|
||||
aVariant = m_value.ToString();
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mikolaj Wielgus
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* https://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef SIM_PROPERTY_H
|
||||
#define SIM_PROPERTY_H
|
||||
|
||||
#include <sim/sim_value.h>
|
||||
#include <wx/propgrid/props.h>
|
||||
|
||||
|
||||
class SIM_VALIDATOR : public wxValidator
|
||||
{
|
||||
public:
|
||||
SIM_VALIDATOR( SIM_VALUE_BASE::TYPE aValueType, SIM_VALUE_PARSER::NOTATION aNotation );
|
||||
SIM_VALIDATOR( const SIM_VALIDATOR& aValidator ) = default;
|
||||
|
||||
wxObject* Clone() const override;
|
||||
|
||||
bool Validate( wxWindow* aParent ) override;
|
||||
bool TransferToWindow() override;
|
||||
bool TransferFromWindow() override;
|
||||
|
||||
private:
|
||||
bool isValid( const wxString& aString );
|
||||
|
||||
wxTextEntry* getTextEntry();
|
||||
|
||||
void onText( wxCommandEvent& aEvent );
|
||||
void onChar( wxKeyEvent& aEvent );
|
||||
void onMouse( wxMouseEvent& aEvent );
|
||||
|
||||
SIM_VALUE_BASE::TYPE m_valueType;
|
||||
SIM_VALUE_PARSER::NOTATION m_notation;
|
||||
wxString m_prevText;
|
||||
long m_prevInsertionPoint;
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
|
||||
class SIM_PROPERTY : public wxStringProperty
|
||||
{
|
||||
public:
|
||||
SIM_PROPERTY( const wxString& aLabel, const wxString& aName, SIM_VALUE_BASE& aValue,
|
||||
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
|
||||
SIM_VALUE_PARSER::NOTATION aNotation = SIM_VALUE_PARSER::NOTATION::SI );
|
||||
|
||||
wxValidator* DoGetValidator() const override;
|
||||
|
||||
bool StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags = 0 )
|
||||
const override;
|
||||
|
||||
protected:
|
||||
SIM_VALUE_BASE::TYPE m_valueType;
|
||||
SIM_VALUE_PARSER::NOTATION m_notation;
|
||||
SIM_VALUE_BASE& m_value;
|
||||
};
|
||||
|
||||
#endif // SIM_PROPERTY_H
|
|
@ -23,8 +23,290 @@
|
|||
*/
|
||||
|
||||
#include <sim/sim_value.h>
|
||||
#include <wx/translation.h>
|
||||
#include <ki_exception.h>
|
||||
#include <locale_io.h>
|
||||
#include <complex>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
|
||||
#define CALL_INSTANCE( ValueType, Notation, func, ... ) \
|
||||
switch( ValueType ) \
|
||||
{ \
|
||||
case SIM_VALUE_BASE::TYPE::INT: \
|
||||
switch( Notation ) \
|
||||
{ \
|
||||
case NOTATION::SI: \
|
||||
func<SIM_VALUE_BASE::TYPE::INT, NOTATION::SI>( __VA_ARGS__ ); \
|
||||
break; \
|
||||
\
|
||||
case NOTATION::SPICE: \
|
||||
func<SIM_VALUE_BASE::TYPE::INT, NOTATION::SPICE>( __VA_ARGS__ ); \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
\
|
||||
case SIM_VALUE_BASE::TYPE::FLOAT: \
|
||||
switch( Notation ) \
|
||||
{ \
|
||||
case NOTATION::SI: \
|
||||
func<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SI>( __VA_ARGS__ ); \
|
||||
break; \
|
||||
\
|
||||
case NOTATION::SPICE: \
|
||||
func<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SPICE>( __VA_ARGS__ ); \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
\
|
||||
case SIM_VALUE_BASE::TYPE::BOOL: \
|
||||
case SIM_VALUE_BASE::TYPE::COMPLEX: \
|
||||
case SIM_VALUE_BASE::TYPE::STRING: \
|
||||
case SIM_VALUE_BASE::TYPE::BOOL_VECTOR: \
|
||||
case SIM_VALUE_BASE::TYPE::INT_VECTOR: \
|
||||
case SIM_VALUE_BASE::TYPE::FLOAT_VECTOR: \
|
||||
case SIM_VALUE_BASE::TYPE::COMPLEX_VECTOR: \
|
||||
wxFAIL_MSG( "Unhandled SIM_VALUE_BASE type" ); \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
|
||||
static inline void doIsValid( tao::pegtl::string_input<>& aIn )
|
||||
{
|
||||
tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn );
|
||||
}
|
||||
|
||||
bool SIM_VALUE_PARSER::IsValid( const wxString& aString,
|
||||
SIM_VALUE_BASE::TYPE aValueType,
|
||||
NOTATION aNotation )
|
||||
{
|
||||
tao::pegtl::string_input<> in( aString, "from_input" );
|
||||
|
||||
try
|
||||
{
|
||||
CALL_INSTANCE( aValueType, aNotation, doIsValid, in );
|
||||
}
|
||||
catch( tao::pegtl::parse_error& e )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
|
||||
static inline std::unique_ptr<tao::pegtl::parse_tree::node> doParse(
|
||||
tao::pegtl::string_input<>& aIn )
|
||||
{
|
||||
return tao::pegtl::parse_tree::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>,
|
||||
SIM_VALUE_PARSER::numberSelector>
|
||||
( aIn );
|
||||
}
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
|
||||
static inline void handleNodeForParse( tao::pegtl::parse_tree::node& aNode,
|
||||
SIM_VALUE_PARSER::PARSE_RESULT& aParseResult )
|
||||
{
|
||||
if( aNode.is_type<SIM_VALUE_PARSER::significand<ValueType>>() )
|
||||
{
|
||||
aParseResult.significand = aNode.string();
|
||||
aParseResult.isEmpty = false;
|
||||
|
||||
for( const auto& subnode : aNode.children )
|
||||
{
|
||||
if( subnode->is_type<SIM_VALUE_PARSER::intPart>() )
|
||||
aParseResult.intPart = std::stol( subnode->string() );
|
||||
else if( subnode->is_type<SIM_VALUE_PARSER::fracPart>() )
|
||||
aParseResult.fracPart = std::stol( subnode->string() );
|
||||
}
|
||||
}
|
||||
else if( aNode.is_type<SIM_VALUE_PARSER::exponent>() )
|
||||
{
|
||||
aParseResult.exponent = std::stol( aNode.string() );
|
||||
aParseResult.isEmpty = false;
|
||||
}
|
||||
else if( aNode.is_type<SIM_VALUE_PARSER::metricSuffix<ValueType, Notation>>() )
|
||||
{
|
||||
aParseResult.metricSuffixExponent =
|
||||
SIM_VALUE_PARSER::MetricSuffixToExponent( aNode.string(), Notation );
|
||||
aParseResult.isEmpty = false;
|
||||
}
|
||||
else
|
||||
wxFAIL_MSG( "Unhandled parse tree node" );
|
||||
}
|
||||
|
||||
SIM_VALUE_PARSER::PARSE_RESULT SIM_VALUE_PARSER::Parse( const wxString& aString,
|
||||
SIM_VALUE_BASE::TYPE aValueType,
|
||||
NOTATION aNotation )
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
|
||||
tao::pegtl::string_input<> in( aString.ToStdString(), "from_input" );
|
||||
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
||||
|
||||
try
|
||||
{
|
||||
CALL_INSTANCE( aValueType, aNotation, root = doParse, in );
|
||||
}
|
||||
catch( tao::pegtl::parse_error& e )
|
||||
{
|
||||
throw KI_PARAM_ERROR( wxString::Format( _( "Failed to parse '%s': %s" ), aString,
|
||||
e.what() ) );
|
||||
}
|
||||
|
||||
wxASSERT( root );
|
||||
|
||||
PARSE_RESULT result;
|
||||
|
||||
try
|
||||
{
|
||||
for( const auto& node : root->children )
|
||||
CALL_INSTANCE( aValueType, aNotation, handleNodeForParse, *node, result );
|
||||
}
|
||||
catch( std::invalid_argument& e )
|
||||
{
|
||||
throw KI_PARAM_ERROR( wxString::Format( _( "Failed to parse '%s': %s" ), aString,
|
||||
e.what() ) );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
long SIM_VALUE_PARSER::MetricSuffixToExponent( std::string aMetricSuffix, NOTATION aNotation )
|
||||
{
|
||||
switch( aNotation )
|
||||
{
|
||||
case NOTATION::SI:
|
||||
if( aMetricSuffix.empty() )
|
||||
return 0;
|
||||
|
||||
switch( aMetricSuffix[0] )
|
||||
{
|
||||
case 'a': return -18;
|
||||
case 'f': return -15;
|
||||
case 'p': return -12;
|
||||
case 'n': return -9;
|
||||
case 'u': return -6;
|
||||
case 'm': return -3;
|
||||
case 'k':
|
||||
case 'K': return 3;
|
||||
case 'M': return 6;
|
||||
case 'G': return 9;
|
||||
case 'T': return 12;
|
||||
case 'P': return 15;
|
||||
case 'E': return 18;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NOTATION::SPICE:
|
||||
std::transform( aMetricSuffix.begin(), aMetricSuffix.end(), aMetricSuffix.begin(),
|
||||
::tolower );
|
||||
|
||||
if( aMetricSuffix == "f" )
|
||||
return -15;
|
||||
else if( aMetricSuffix == "p" )
|
||||
return -12;
|
||||
else if( aMetricSuffix == "n" )
|
||||
return -9;
|
||||
else if( aMetricSuffix == "u" )
|
||||
return -6;
|
||||
else if( aMetricSuffix == "m" )
|
||||
return -3;
|
||||
else if( aMetricSuffix == "" )
|
||||
return 0;
|
||||
else if( aMetricSuffix == "k" )
|
||||
return 3;
|
||||
else if( aMetricSuffix == "meg" )
|
||||
return 6;
|
||||
else if( aMetricSuffix == "g" )
|
||||
return 9;
|
||||
else if( aMetricSuffix == "t" )
|
||||
return 12;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
throw KI_PARAM_ERROR( wxString::Format( _( "Unknown simulator value suffix: \"%s\"" ),
|
||||
aMetricSuffix ) );
|
||||
}
|
||||
|
||||
|
||||
wxString SIM_VALUE_PARSER::ExponentToMetricSuffix( double aExponent, long& aReductionExponent,
|
||||
NOTATION aNotation )
|
||||
{
|
||||
if( aNotation == NOTATION::SI && aExponent >= -18 && aExponent <= -15 )
|
||||
{
|
||||
aReductionExponent = -18;
|
||||
return "a";
|
||||
}
|
||||
else if( aExponent > -15 && aExponent <= -12 )
|
||||
{
|
||||
aReductionExponent = -15;
|
||||
return "f";
|
||||
}
|
||||
else if( aExponent > -12 && aExponent <= -9 )
|
||||
{
|
||||
aReductionExponent = -12;
|
||||
return "p";
|
||||
}
|
||||
else if( aExponent > -9 && aExponent <= -6 )
|
||||
{
|
||||
aReductionExponent = -9;
|
||||
return "n";
|
||||
}
|
||||
else if( aExponent > -6 && aExponent <= -3 )
|
||||
{
|
||||
aReductionExponent = -6;
|
||||
return "u";
|
||||
}
|
||||
else if( aExponent > -3 && aExponent < 0 )
|
||||
{
|
||||
aReductionExponent = -3;
|
||||
return "m";
|
||||
}
|
||||
else if( aExponent > 0 && aExponent < 3 )
|
||||
{
|
||||
aReductionExponent = 0;
|
||||
return "";
|
||||
}
|
||||
else if( aExponent >= 3 && aExponent < 6 )
|
||||
{
|
||||
aReductionExponent = 3;
|
||||
return "k";
|
||||
}
|
||||
else if( aExponent >= 6 && aExponent < 9 )
|
||||
{
|
||||
aReductionExponent = 6;
|
||||
return ( aNotation == NOTATION::SI ) ? "M" : "Meg";
|
||||
}
|
||||
else if( aExponent >= 9 && aExponent < 12 )
|
||||
{
|
||||
aReductionExponent = 9;
|
||||
return "G";
|
||||
}
|
||||
else if( aExponent >= 12 && aExponent < 15 )
|
||||
{
|
||||
aReductionExponent = 12;
|
||||
return "T";
|
||||
}
|
||||
else if( aNotation == NOTATION::SI && aExponent >= 15 && aExponent < 18 )
|
||||
{
|
||||
aReductionExponent = 15;
|
||||
return "P";
|
||||
}
|
||||
else if( aNotation == NOTATION::SI && aExponent >= 18 && aExponent <= 21 )
|
||||
{
|
||||
aReductionExponent = 18;
|
||||
return "E";
|
||||
}
|
||||
|
||||
aReductionExponent = 0;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_VALUE_BASE> SIM_VALUE_BASE::Create( TYPE aType, wxString aString )
|
||||
|
@ -50,7 +332,7 @@ std::unique_ptr<SIM_VALUE_BASE> SIM_VALUE_BASE::Create( TYPE aType )
|
|||
case TYPE::COMPLEX_VECTOR: return std::make_unique<SIM_VALUE<std::complex<double>>>();
|
||||
}
|
||||
|
||||
wxFAIL_MSG( "Unknown SIM_VALUE type" );
|
||||
wxFAIL_MSG( _( "Unknown SIM_VALUE type" ) );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -62,15 +344,105 @@ void SIM_VALUE_BASE::operator=( const wxString& aString )
|
|||
|
||||
|
||||
template <typename T>
|
||||
SIM_VALUE<T>::SIM_VALUE( const T& aValue ) : m_value(aValue)
|
||||
SIM_VALUE<T>::SIM_VALUE( const T& aValue ) : m_value( aValue )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_VALUE<T>::FromString( const wxString& aString )
|
||||
template <>
|
||||
void SIM_VALUE<bool>::FromString( const wxString& aString )
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString );
|
||||
|
||||
if( parseResult.isEmpty )
|
||||
{
|
||||
m_value = NULLOPT;
|
||||
return;
|
||||
}
|
||||
|
||||
if( !parseResult.intPart
|
||||
|| ( *parseResult.intPart != 0 && *parseResult.intPart != 1 )
|
||||
|| parseResult.fracPart
|
||||
|| parseResult.exponent
|
||||
|| parseResult.metricSuffixExponent )
|
||||
{
|
||||
throw KI_PARAM_ERROR( wxString::Format( _( "Invalid Bool simulator value string: '%s'" ),
|
||||
aString ) );
|
||||
|
||||
}
|
||||
|
||||
m_value = *parseResult.intPart;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void SIM_VALUE<long>::FromString( const wxString& aString )
|
||||
{
|
||||
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString );
|
||||
|
||||
if( parseResult.isEmpty )
|
||||
{
|
||||
m_value = NULLOPT;
|
||||
return;
|
||||
}
|
||||
|
||||
if( !parseResult.intPart || parseResult.fracPart )
|
||||
{
|
||||
throw KI_PARAM_ERROR( wxString::Format( _( "Invalid Int simulator value string: '%s'" ),
|
||||
aString ) );
|
||||
}
|
||||
|
||||
long exponent = parseResult.exponent ? *parseResult.exponent : 0;
|
||||
exponent += parseResult.metricSuffixExponent ? *parseResult.metricSuffixExponent : 0;
|
||||
|
||||
m_value = static_cast<double>( *parseResult.intPart ) * std::pow( 10, exponent );
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void SIM_VALUE<double>::FromString( const wxString& aString )
|
||||
{
|
||||
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString );
|
||||
|
||||
// Single dot should be allowed in fields.
|
||||
// TODO: disallow single dot in models.
|
||||
if( parseResult.isEmpty || parseResult.significand == "." )
|
||||
{
|
||||
m_value = NULLOPT;
|
||||
return;
|
||||
}
|
||||
|
||||
if( parseResult.significand.empty() )
|
||||
throw KI_PARAM_ERROR( wxString::Format( _( "Invalid Float simulator value string: '%s'" ),
|
||||
aString ) );
|
||||
|
||||
long exponent = parseResult.exponent ? *parseResult.exponent : 0;
|
||||
exponent += parseResult.metricSuffixExponent ? *parseResult.metricSuffixExponent : 0;
|
||||
|
||||
m_value = std::stod( parseResult.significand ) * std::pow( 10, exponent );
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void SIM_VALUE<std::complex<double>>::FromString( const wxString& aString )
|
||||
{
|
||||
// TODO
|
||||
|
||||
/*LOCALE_IO toggle;
|
||||
|
||||
double value = 0;
|
||||
|
||||
if( !aString.ToDouble( &value ) )
|
||||
throw KI_PARAM_ERROR( _( "Invalid complex sim value string" ) );
|
||||
|
||||
m_value = value;*/
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void SIM_VALUE<wxString>::FromString( const wxString& aString )
|
||||
{
|
||||
m_value = aString;
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +467,11 @@ template <>
|
|||
wxString SIM_VALUE<bool>::ToString() const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
return wxString::Format( "%d", m_value );
|
||||
|
||||
if( m_value.has_value() )
|
||||
return wxString::Format( "%d", *m_value );
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,7 +479,20 @@ template <>
|
|||
wxString SIM_VALUE<long>::ToString() const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
return wxString::Format( "%d", m_value );
|
||||
|
||||
if( m_value.has_value() )
|
||||
{
|
||||
double exponent = std::log10( *m_value );
|
||||
long reductionExponent = 0;
|
||||
|
||||
wxString metricSuffix = SIM_VALUE_PARSER::ExponentToMetricSuffix( exponent,
|
||||
reductionExponent );
|
||||
long reducedValue = *m_value / static_cast<long>( std::pow( 10, reductionExponent ) );
|
||||
|
||||
return wxString::Format( "%d%s", reducedValue, metricSuffix );
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,7 +500,20 @@ template <>
|
|||
wxString SIM_VALUE<double>::ToString() const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
return wxString::Format( "%f", m_value );
|
||||
|
||||
if( m_value.has_value() )
|
||||
{
|
||||
double exponent = std::log10( *m_value );
|
||||
long reductionExponent = 0;
|
||||
|
||||
wxString metricSuffix = SIM_VALUE_PARSER::ExponentToMetricSuffix( exponent,
|
||||
reductionExponent );
|
||||
double reducedValue = *m_value / std::pow( 10, reductionExponent );
|
||||
|
||||
return wxString::Format( "%g%s", reducedValue, metricSuffix );
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,7 +521,11 @@ template <>
|
|||
wxString SIM_VALUE<std::complex<double>>::ToString() const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
return wxString::Format( "%f+%fi", m_value.real(), m_value.imag() );
|
||||
|
||||
if( m_value.has_value() )
|
||||
return wxString::Format( "%g+%gi", m_value->real(), m_value->imag() );
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,7 +533,38 @@ template <>
|
|||
wxString SIM_VALUE<wxString>::ToString() const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
return m_value;
|
||||
|
||||
if( m_value.has_value() )
|
||||
return *m_value;
|
||||
|
||||
return ""; // Empty string is completely equivalent to null string.
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
wxString SIM_VALUE<T>::ToSimpleString() const
|
||||
{
|
||||
if( m_value.has_value() )
|
||||
{
|
||||
wxString result = "";
|
||||
result << *m_value;
|
||||
return result;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
wxString SIM_VALUE<std::complex<double>>::ToSimpleString() const
|
||||
{
|
||||
// TODO
|
||||
|
||||
/*wxString result = "";
|
||||
result << *m_value;
|
||||
|
||||
return result;*/
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
#ifndef SIM_VALUE_H
|
||||
#define SIM_VALUE_H
|
||||
|
||||
#include <memory>
|
||||
#include <wx/string.h>
|
||||
#include <core/optional.h>
|
||||
#include <memory>
|
||||
#include <pegtl.hpp>
|
||||
|
||||
|
||||
class SIM_VALUE_BASE
|
||||
{
|
||||
|
@ -48,11 +51,17 @@ public:
|
|||
static std::unique_ptr<SIM_VALUE_BASE> Create( TYPE aType, wxString aString );
|
||||
static std::unique_ptr<SIM_VALUE_BASE> Create( TYPE aType );
|
||||
|
||||
virtual ~SIM_VALUE_BASE() = default;
|
||||
SIM_VALUE_BASE() = default;
|
||||
|
||||
void operator=( const wxString& aString );
|
||||
virtual bool operator==( const SIM_VALUE_BASE& aOther ) const = 0;
|
||||
|
||||
virtual void FromString( const wxString& aString ) = 0;
|
||||
virtual wxString ToString() const = 0;
|
||||
|
||||
// For parsers that don't accept strings with our suffixes.
|
||||
virtual wxString ToSimpleString() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -65,12 +74,134 @@ public:
|
|||
|
||||
void FromString( const wxString& aString ) override;
|
||||
wxString ToString() const override;
|
||||
wxString ToSimpleString() const override;
|
||||
|
||||
void operator=( const T& aValue );
|
||||
bool operator==( const SIM_VALUE_BASE& aOther ) const override;
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
OPT<T> m_value = NULLOPT;
|
||||
|
||||
wxString getMetricSuffix();
|
||||
};
|
||||
|
||||
#endif /* SIM_VALUE_H */
|
||||
|
||||
namespace SIM_VALUE_PARSER
|
||||
{
|
||||
using namespace tao::pegtl;
|
||||
|
||||
enum class NOTATION
|
||||
{
|
||||
SI,
|
||||
SPICE
|
||||
};
|
||||
|
||||
template <NOTATION Notation>
|
||||
wxString allowedIntChars;
|
||||
|
||||
|
||||
struct spaces : plus<space> {};
|
||||
struct digits : plus<tao::pegtl::digit> {}; // For some reason it fails on just "digit".
|
||||
|
||||
struct sign : one<'+', '-'> {};
|
||||
|
||||
struct intPart : digits {};
|
||||
|
||||
//struct fracPartPrefix : one<'.'> {};
|
||||
struct fracPart : digits {};
|
||||
//struct fracPartWithPrefix : seq<fracPartPrefix, fracPart> {};
|
||||
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType>
|
||||
struct significand;
|
||||
|
||||
template <> struct significand<SIM_VALUE_BASE::TYPE::FLOAT> :
|
||||
sor<seq<intPart, one<'.'>, fracPart>,
|
||||
seq<intPart, one<'.'>>,
|
||||
intPart,
|
||||
seq<one<'.'>, fracPart>,
|
||||
one<'.'>> {};
|
||||
|
||||
template <> struct significand<SIM_VALUE_BASE::TYPE::INT> : intPart {};
|
||||
|
||||
|
||||
struct exponentPrefix : one<'e', 'E'> {};
|
||||
struct exponent : seq<opt<sign>, opt<digits>> {};
|
||||
struct exponentWithPrefix : seq<exponentPrefix, exponent> {};
|
||||
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType, NOTATION Notation>
|
||||
struct metricSuffix;
|
||||
|
||||
template <> struct metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SI>
|
||||
: one<'k', 'K', 'M', 'G', 'T', 'P', 'E'> {};
|
||||
template <> struct metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SPICE>
|
||||
: sor<TAO_PEGTL_ISTRING( "k" ),
|
||||
TAO_PEGTL_ISTRING( "Meg" ),
|
||||
TAO_PEGTL_ISTRING( "G" ),
|
||||
TAO_PEGTL_ISTRING( "T" )> {};
|
||||
|
||||
template <> struct metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SI>
|
||||
: one<'a', 'f', 'p', 'n', 'u', 'm', 'k', 'K', 'M', 'G', 'T', 'P', 'E'> {};
|
||||
template <> struct metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SPICE>
|
||||
: sor<TAO_PEGTL_ISTRING( "f" ),
|
||||
TAO_PEGTL_ISTRING( "p" ),
|
||||
TAO_PEGTL_ISTRING( "n" ),
|
||||
TAO_PEGTL_ISTRING( "u" ),
|
||||
TAO_PEGTL_ISTRING( "m" ),
|
||||
//TAO_PEGTL_ISTRING( "mil" ),
|
||||
TAO_PEGTL_ISTRING( "k" ),
|
||||
TAO_PEGTL_ISTRING( "Meg" ),
|
||||
TAO_PEGTL_ISTRING( "G" ),
|
||||
TAO_PEGTL_ISTRING( "T" )> {};
|
||||
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType, NOTATION Notation>
|
||||
struct number : seq<significand<ValueType>,
|
||||
opt<exponentWithPrefix>,
|
||||
opt<metricSuffix<ValueType, Notation>>> {};
|
||||
|
||||
template <SIM_VALUE_BASE::TYPE ValueType, NOTATION Notation>
|
||||
struct numberGrammar : must<opt<number<ValueType, Notation>>, eof> {};
|
||||
|
||||
|
||||
template <typename Rule>
|
||||
struct numberSelector : std::false_type {};
|
||||
|
||||
template <> struct numberSelector<significand<SIM_VALUE_BASE::TYPE::INT>> : std::true_type {};
|
||||
template <> struct numberSelector<significand<SIM_VALUE_BASE::TYPE::FLOAT>> : std::true_type {};
|
||||
template <> struct numberSelector<intPart> : std::true_type {};
|
||||
template <> struct numberSelector<fracPart> : std::true_type {};
|
||||
template <> struct numberSelector<exponent> : std::true_type {};
|
||||
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SI>>
|
||||
: std::true_type {};
|
||||
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SPICE>>
|
||||
: std::true_type {};
|
||||
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SI>>
|
||||
: std::true_type {};
|
||||
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SPICE>>
|
||||
: std::true_type {};
|
||||
|
||||
struct PARSE_RESULT
|
||||
{
|
||||
bool isEmpty = true;
|
||||
std::string significand;
|
||||
OPT<long> intPart;
|
||||
OPT<long> fracPart;
|
||||
OPT<long> exponent;
|
||||
OPT<long> metricSuffixExponent;
|
||||
};
|
||||
|
||||
bool IsValid( const wxString& aString,
|
||||
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
|
||||
NOTATION aNotation = NOTATION::SI );
|
||||
PARSE_RESULT Parse( const wxString& aString,
|
||||
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
|
||||
NOTATION aNotation = NOTATION::SI );
|
||||
|
||||
long MetricSuffixToExponent( std::string aMetricSuffix, NOTATION aNotation = NOTATION::SI );
|
||||
wxString ExponentToMetricSuffix( double aExponent, long& aReductionExponent,
|
||||
NOTATION aNotation = NOTATION::SI );
|
||||
}
|
||||
|
||||
#endif // SIM_VALUE_H
|
||||
|
|
|
@ -73,10 +73,10 @@ BOOST_AUTO_TEST_CASE( Models )
|
|||
BOOST_CHECK_EQUAL( instanceParamCount, 5 );
|
||||
break;
|
||||
|
||||
case NGSPICE::MODEL_TYPE::TRANSLINE:
|
||||
/*case NGSPICE::MODEL_TYPE::TRANSLINE:
|
||||
BOOST_CHECK_EQUAL( modelParamCount, 6 );
|
||||
BOOST_CHECK_EQUAL( instanceParamCount, 3 );
|
||||
break;
|
||||
break;*/
|
||||
|
||||
case NGSPICE::MODEL_TYPE::DIODE:
|
||||
BOOST_CHECK_EQUAL( modelParamCount, 76 );
|
||||
|
|
Loading…
Reference in New Issue