Add simple VI model inference.
This commit is contained in:
parent
f8d2bdbdf9
commit
7192c565b8
|
@ -133,35 +133,31 @@ template <typename T_symbol, typename T_field>
|
|||
bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
||||
{
|
||||
wxCommandEvent dummyEvent;
|
||||
wxString deviceType;
|
||||
wxString modelType;
|
||||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
|
||||
// Infer RLC models if they aren't specified
|
||||
if( !m_symbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD )
|
||||
&& !m_symbol.FindField( SIM_MODEL::PARAMS_FIELD ) )
|
||||
// Infer RLC and VI models if they aren't specified
|
||||
if( SIM_MODEL::InferSimModel<T_symbol, T_field>( m_symbol, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
||||
&deviceType, &modelType, &modelParams, &pinMap ) )
|
||||
{
|
||||
wxString modelType;
|
||||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||
m_fields.back().SetText( deviceType );
|
||||
|
||||
if( SIM_MODEL::InferPassiveSimModel( m_symbol, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
||||
&modelType, &modelParams, &pinMap ) )
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||
m_fields.back().SetText( m_symbol.GetPrefix().Left( 1 ) );
|
||||
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||
m_fields.back().SetText( modelType );
|
||||
}
|
||||
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||
m_fields.back().SetText( modelParams );
|
||||
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::PINS_FIELD );
|
||||
m_fields.back().SetText( pinMap );
|
||||
|
||||
m_fields[ VALUE_FIELD ].SetText( wxT( "${SIM.PARAMS}" ) );
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||
m_fields.back().SetText( modelType );
|
||||
}
|
||||
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||
m_fields.back().SetText( modelParams );
|
||||
|
||||
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::PINS_FIELD );
|
||||
m_fields.back().SetText( pinMap );
|
||||
|
||||
m_fields[ VALUE_FIELD ].SetText( wxT( "${SIM.PARAMS}" ) );
|
||||
}
|
||||
|
||||
std::string libraryFilename = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::LIBRARY_FIELD );
|
||||
|
@ -264,10 +260,10 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
|||
+ e.What() );
|
||||
}
|
||||
|
||||
SIM_MODEL::DEVICE_T deviceType = SIM_MODEL::TypeInfo( type ).deviceType;
|
||||
SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType;
|
||||
|
||||
if( !m_curModelTypeOfDeviceType.count( deviceType ) )
|
||||
m_curModelTypeOfDeviceType[deviceType] = type;
|
||||
if( !m_curModelTypeOfDeviceType.count( deviceTypeT ) )
|
||||
m_curModelTypeOfDeviceType[deviceTypeT] = type;
|
||||
}
|
||||
|
||||
m_saveInValueCheckbox->SetValue( curModel().IsStoredInValue() );
|
||||
|
|
|
@ -232,33 +232,31 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
spiceItem.fields.back().SetText( symbol->GetFields()[i].GetShownText( 0, false ) );
|
||||
}
|
||||
|
||||
// Infer RLC models if they aren't specified
|
||||
if( !symbol->FindField( SIM_MODEL::DEVICE_TYPE_FIELD, false )
|
||||
&& !symbol->FindField( SIM_MODEL::PARAMS_FIELD, false ) )
|
||||
wxString deviceType;
|
||||
wxString modelType;
|
||||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
|
||||
// Infer RLC and VI models if they aren't specified
|
||||
if( SIM_MODEL::InferSimModel<SCH_SYMBOL, SCH_FIELD>( *symbol, true,
|
||||
SIM_VALUE_GRAMMAR::NOTATION::SPICE,
|
||||
&deviceType, &modelType,
|
||||
&modelParams, &pinMap ) )
|
||||
{
|
||||
wxString modelType;
|
||||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||
spiceItem.fields.back().SetText( deviceType );
|
||||
|
||||
if( SIM_MODEL::InferPassiveSimModel( *symbol, true,
|
||||
SIM_VALUE_GRAMMAR::NOTATION::SPICE,
|
||||
&modelType, &modelParams, &pinMap ) )
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||
spiceItem.fields.back().SetText( symbol->GetPrefix().Left( 1 ) );
|
||||
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||
spiceItem.fields.back().SetText( modelType );
|
||||
}
|
||||
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||
spiceItem.fields.back().SetText( modelParams );
|
||||
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::PINS_FIELD );
|
||||
spiceItem.fields.back().SetText( pinMap );
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||
spiceItem.fields.back().SetText( modelType );
|
||||
}
|
||||
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||
spiceItem.fields.back().SetText( modelParams );
|
||||
|
||||
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::PINS_FIELD );
|
||||
spiceItem.fields.back().SetText( pinMap );
|
||||
}
|
||||
|
||||
try
|
||||
|
|
|
@ -197,32 +197,31 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, S
|
|||
fields.back().SetText( aSymbol.GetFields()[ i ].GetShownText( 0, false ) );
|
||||
}
|
||||
|
||||
// Infer RLC models if they aren't specified
|
||||
if( !aSymbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD, false )
|
||||
&& !aSymbol.FindField( SIM_MODEL::PARAMS_FIELD, false ) )
|
||||
wxString deviceType;
|
||||
wxString modelType;
|
||||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
|
||||
// Infer RLC and VI models if they aren't specified
|
||||
if( SIM_MODEL::InferSimModel<SCH_SYMBOL, SCH_FIELD>( aSymbol, true,
|
||||
SIM_VALUE_GRAMMAR::NOTATION::SI,
|
||||
&deviceType, &modelType, &modelParams,
|
||||
&pinMap ) )
|
||||
{
|
||||
wxString modelType;
|
||||
wxString modelParams;
|
||||
wxString pinMap;
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||
fields.back().SetText( deviceType );
|
||||
|
||||
if( SIM_MODEL::InferPassiveSimModel( aSymbol, true, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
||||
&modelType, &modelParams, &pinMap ) )
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
|
||||
fields.back().SetText( aSymbol.GetPrefix().Left( 1 ) );
|
||||
|
||||
if( !modelType.IsEmpty() )
|
||||
{
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||
fields.back().SetText( modelType );
|
||||
}
|
||||
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||
fields.back().SetText( modelParams );
|
||||
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::PINS_FIELD );
|
||||
fields.back().SetText( pinMap );
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::TYPE_FIELD );
|
||||
fields.back().SetText( modelType );
|
||||
}
|
||||
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::PARAMS_FIELD );
|
||||
fields.back().SetText( modelParams );
|
||||
|
||||
fields.emplace_back( &aSymbol, -1, SIM_MODEL::PINS_FIELD );
|
||||
fields.back().SetText( pinMap );
|
||||
}
|
||||
|
||||
std::vector<LIB_PIN*> sourcePins = aSymbol.GetAllLibPins();
|
||||
|
|
|
@ -1049,103 +1049,184 @@ bool SIM_MODEL::requiresSpiceModelLine() const
|
|||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
bool SIM_MODEL::InferPassiveSimModel( T& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aModelType,
|
||||
wxString* aModelParams, wxString* aPinMap )
|
||||
template <class T_symbol, class T_field>
|
||||
bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aDeviceType,
|
||||
wxString* aModelType, wxString* aModelParams, wxString* aPinMap )
|
||||
{
|
||||
wxString aPrefix = aSymbol.GetPrefix();
|
||||
wxString aValue;
|
||||
auto convertNotation =
|
||||
[&]( const wxString& units ) -> wxString
|
||||
{
|
||||
if( aNotation == SIM_VALUE_GRAMMAR::NOTATION::SPICE )
|
||||
{
|
||||
if( units == wxT( "M" ) )
|
||||
return wxT( "Meg" );
|
||||
}
|
||||
else if( aNotation == SIM_VALUE_GRAMMAR::NOTATION::SI )
|
||||
{
|
||||
if( units == wxT( "Meg" ) || units == wxT( "MEG" ) )
|
||||
return wxT( "M" );
|
||||
}
|
||||
|
||||
if( aResolve )
|
||||
aValue = aSymbol.FindField( VALUE_FIELD )->GetShownText();
|
||||
else
|
||||
aValue = aSymbol.FindField( VALUE_FIELD )->GetText();
|
||||
return units;
|
||||
};
|
||||
|
||||
if( !aValue.IsEmpty() )
|
||||
auto getFieldValue =
|
||||
[&]( const wxString& fieldName ) -> wxString
|
||||
{
|
||||
T_field* field = aSymbol.FindField( fieldName );
|
||||
|
||||
if( field )
|
||||
{
|
||||
if( aResolve )
|
||||
return field->GetShownText();
|
||||
else
|
||||
return field->GetText();
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
};
|
||||
|
||||
wxString prefix = aSymbol.GetPrefix();
|
||||
wxString value = getFieldValue( VALUE_FIELD );
|
||||
std::vector<LIB_PIN*> pins = aSymbol.GetAllLibPins();
|
||||
|
||||
*aDeviceType = getFieldValue( DEVICE_TYPE_FIELD );
|
||||
*aModelType = getFieldValue( TYPE_FIELD );
|
||||
*aModelParams = getFieldValue( PARAMS_FIELD );
|
||||
*aPinMap = getFieldValue( PINS_FIELD );
|
||||
|
||||
if( pins.size() != 2 )
|
||||
return false;
|
||||
|
||||
if( aDeviceType->IsEmpty()
|
||||
&& aModelType->IsEmpty()
|
||||
&& !value.IsEmpty()
|
||||
&& ( prefix.StartsWith( "R" ) || prefix.StartsWith( "L" ) || prefix.StartsWith( "C" ) ) )
|
||||
{
|
||||
if( aPrefix.StartsWith( wxT( "R" ) )
|
||||
|| aPrefix.StartsWith( wxT( "L" ) )
|
||||
|| aPrefix.StartsWith( wxT( "C" ) ) )
|
||||
if( aDeviceType->IsEmpty() )
|
||||
*aDeviceType = prefix.Left( 1 );
|
||||
|
||||
if( aModelParams->IsEmpty() )
|
||||
{
|
||||
wxRegEx idealVal( wxT( "^"
|
||||
"([0-9\\. ]+)"
|
||||
"([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?"
|
||||
"([fFhHΩΩ𝛀𝛺𝝮]|ohm)?"
|
||||
"([fFhHΩΩ𝛀𝛺𝝮rR]|ohm)?"
|
||||
"([-1-9 ]*)"
|
||||
"([fFhHΩΩ𝛀𝛺𝝮rR]|ohm)?"
|
||||
"$" ) );
|
||||
|
||||
if( idealVal.Matches( aValue ) ) // Ideal
|
||||
if( idealVal.Matches( value ) ) // Ideal
|
||||
{
|
||||
wxString valuePrefix( idealVal.GetMatch( aValue, 1 ) );
|
||||
wxString valueUnits( idealVal.GetMatch( aValue, 2 ) );
|
||||
wxString valueSuffix( idealVal.GetMatch( aValue, 6 ) );
|
||||
wxString valueMantissa( idealVal.GetMatch( value, 1 ) );
|
||||
wxString valueNotation( idealVal.GetMatch( value, 2 ) );
|
||||
wxString valueFraction( idealVal.GetMatch( value, 6 ) );
|
||||
|
||||
if( aNotation == SIM_VALUE_GRAMMAR::NOTATION::SPICE )
|
||||
if( valueMantissa.Contains( wxT( "." ) ) )
|
||||
{
|
||||
if( valueUnits == wxT( "M" ) )
|
||||
valueUnits = wxT( "Meg" );
|
||||
aModelParams->Printf( wxT( "%s=\"%s%s\"" ),
|
||||
prefix.Left(1).Lower(),
|
||||
valueMantissa, convertNotation( valueNotation ) );
|
||||
}
|
||||
else if( aNotation == SIM_VALUE_GRAMMAR::NOTATION::SI )
|
||||
else
|
||||
{
|
||||
if( valueUnits == wxT( "Meg" ) || valueUnits == wxT( "MEG" ) )
|
||||
valueUnits = wxT( "M" );
|
||||
aModelParams->Printf( wxT( "%s=\"%s.%s%s\"" ),
|
||||
prefix.Left(1).Lower(),
|
||||
valueMantissa,
|
||||
valueFraction,
|
||||
convertNotation( valueNotation ) );
|
||||
}
|
||||
|
||||
aModelParams->Printf( wxT( "%s=\"%s%s\"" ),
|
||||
aPrefix.Left(1).Lower(),
|
||||
valuePrefix,
|
||||
valueUnits );
|
||||
}
|
||||
else // Behavioral
|
||||
{
|
||||
*aModelType = wxT( "=" );
|
||||
aModelParams->Printf( wxT( "%s=\"%s\"" ),
|
||||
aPrefix.Left(1).Lower(),
|
||||
aValue );
|
||||
aModelParams->Printf( wxT( "%s=\"%s\"" ), prefix.Left(1).Lower(), value );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_PIN*> pins = aSymbol.GetAllLibPins();
|
||||
if( aPinMap->IsEmpty() )
|
||||
aPinMap->Printf( wxT( "%s=+ %s=-" ), pins[0]->GetNumber(), pins[1]->GetNumber() );
|
||||
|
||||
if( pins.size() == 2 )
|
||||
return true;
|
||||
}
|
||||
|
||||
bool inferDCSource = false;
|
||||
|
||||
if( ( ( *aDeviceType == wxT( "V" ) || *aDeviceType == wxT( "I" ) )
|
||||
&& aModelType->IsEmpty() )
|
||||
|
||||
||
|
||||
|
||||
( aDeviceType->IsEmpty()
|
||||
&& aModelType->IsEmpty()
|
||||
&& !value.IsEmpty()
|
||||
&& ( prefix.StartsWith( "V" ) || prefix.StartsWith( "I" ) ) ) )
|
||||
{
|
||||
if( aDeviceType->IsEmpty() )
|
||||
*aDeviceType = prefix.Left( 1 );
|
||||
|
||||
if( aModelType->IsEmpty() )
|
||||
*aModelType = wxT( "DC" );
|
||||
|
||||
if( aModelParams->IsEmpty() )
|
||||
{
|
||||
wxRegEx sourceVal( wxT( "^"
|
||||
"([0-9\\. ]+)"
|
||||
"([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?"
|
||||
"([vVaA])?"
|
||||
"([-1-9 ]*)"
|
||||
"([vVaA])?"
|
||||
"$" ) );
|
||||
|
||||
if( sourceVal.Matches( value ) )
|
||||
{
|
||||
aPinMap->Printf( wxT( "%s=+ %s=-" ),
|
||||
pins[0]->GetNumber(),
|
||||
pins[1]->GetNumber() );
|
||||
wxString valueMantissa( sourceVal.GetMatch( value, 1 ) );
|
||||
wxString valueNotation( sourceVal.GetMatch( value, 2 ) );
|
||||
wxString valueFraction( sourceVal.GetMatch( value, 6 ) );
|
||||
|
||||
if( valueMantissa.Contains( wxT( "." ) ) )
|
||||
{
|
||||
aModelParams->Printf( wxT( "dc=\"%s%s\"" ),
|
||||
valueMantissa,
|
||||
convertNotation( valueNotation ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aModelParams->Printf( wxT( "dc=\"%s.%s%s\"" ),
|
||||
valueMantissa,
|
||||
valueFraction,
|
||||
convertNotation( valueNotation ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*aPinMap = wxEmptyString;
|
||||
|
||||
for( unsigned ii = 0; ii < pins.size(); ++ii )
|
||||
{
|
||||
if( ii > 0 )
|
||||
aPinMap->Append( wxS( " " ) );
|
||||
|
||||
aPinMap->Append( wxString::Format( wxT( "%s=%u" ),
|
||||
pins[ii]->GetNumber(),
|
||||
ii ) );
|
||||
}
|
||||
aModelParams->Printf( wxT( "dc=\"%s\"" ), value );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( aPinMap->IsEmpty() )
|
||||
aPinMap->Printf( wxT( "%s=+ %s=-" ), pins[0]->GetNumber(), pins[1]->GetNumber() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template bool SIM_MODEL::InferPassiveSimModel<SCH_SYMBOL>( SCH_SYMBOL& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation,
|
||||
wxString* aModelType,
|
||||
wxString* aModelParams,
|
||||
wxString* aPinMap );
|
||||
template bool SIM_MODEL::InferPassiveSimModel<LIB_SYMBOL>( LIB_SYMBOL& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation,
|
||||
wxString* aModelType,
|
||||
wxString* aModelParams,
|
||||
wxString* aPinMap );
|
||||
template bool SIM_MODEL::InferSimModel<SCH_SYMBOL, SCH_FIELD>( SCH_SYMBOL& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation,
|
||||
wxString* aDeviceType,
|
||||
wxString* aModelType,
|
||||
wxString* aModelParams,
|
||||
wxString* aPinMap );
|
||||
template bool SIM_MODEL::InferSimModel<LIB_SYMBOL, LIB_FIELD>( LIB_SYMBOL& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation,
|
||||
wxString* aDeviceType,
|
||||
wxString* aModelType,
|
||||
wxString* aModelParams,
|
||||
wxString* aPinMap );
|
||||
|
||||
|
||||
template <typename T_symbol, typename T_field>
|
||||
|
|
|
@ -518,10 +518,10 @@ public:
|
|||
|
||||
virtual void SwitchSingleEndedDiff( bool aDiff ) { };
|
||||
|
||||
template <class T>
|
||||
static bool InferPassiveSimModel( T& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aModelType,
|
||||
wxString* aModelParams, wxString* aPinMap );
|
||||
template <class T_symbol, class T_field>
|
||||
static bool InferSimModel( T_symbol& aSymbol, bool aResolve,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aDeviceType,
|
||||
wxString* aModelType, wxString* aModelParams, wxString* aPinMap );
|
||||
|
||||
template <class T_symbol, class T_field>
|
||||
static void MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject );
|
||||
|
|
Loading…
Reference in New Issue