Simulation bug fixes.

1) Use C-locale when converting output of parsers to strings.

2) InferSimModel() must run on local copy of fields, not the fields in
the symbol (which might be different if they've already been edited in
the Symbol Properties Dialog, for instance).

3) InferSimModel() should accept a deviceType already set to RLC.

4) Don't output trailing decimal separators if there's no fraction.
This commit is contained in:
Jeff Young 2022-12-19 18:10:57 +00:00
parent f601c87cea
commit 58ce0bb804
6 changed files with 48 additions and 54 deletions

View File

@ -139,7 +139,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
wxString pinMap;
// 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,
if( SIM_MODEL::InferSimModel( m_symbol, &m_fields, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
&deviceType, &modelType, &modelParams, &pinMap ) )
{
m_fields.emplace_back( &m_symbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );

View File

@ -238,10 +238,9 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
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 ) )
if( SIM_MODEL::InferSimModel( *symbol, &spiceItem.fields, true,
SIM_VALUE_GRAMMAR::NOTATION::SPICE, &deviceType,
&modelType, &modelParams, &pinMap ) )
{
spiceItem.fields.emplace_back( symbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
spiceItem.fields.back().SetText( deviceType );

View File

@ -203,10 +203,8 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, S
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 ) )
if( SIM_MODEL::InferSimModel( aSymbol, &fields, true, SIM_VALUE_GRAMMAR::NOTATION::SI,
&deviceType, &modelType, &modelParams, &pinMap ) )
{
fields.emplace_back( &aSymbol, -1, SIM_MODEL::DEVICE_TYPE_FIELD );
fields.back().SetText( deviceType );

View File

@ -524,7 +524,8 @@ template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<LIB_FIE
template <typename T>
std::string SIM_MODEL::GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName )
std::string SIM_MODEL::GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName,
bool aResolve )
{
static_assert( std::is_same<T, SCH_FIELD>::value || std::is_same<T, LIB_FIELD>::value );
@ -537,17 +538,19 @@ std::string SIM_MODEL::GetFieldValue( const std::vector<T>* aFields, const std::
return field.GetName() == aFieldName;
} );
if( it != aFields->end() )
return std::string( it->GetText().ToUTF8() );
if( it == aFields->end() )
return "";
else if( aResolve )
return std::string( it->GetShownText().ToUTF8() );
else
return std::string( it->GetText().ToUTF8() );
}
// This specialization is used when no fields are passed.
template <>
std::string SIM_MODEL::GetFieldValue( const std::vector<void>* aFields,
const std::string& aFieldName )
const std::string& aFieldName, bool aResolve )
{
return "";
}
@ -1050,7 +1053,7 @@ bool SIM_MODEL::requiresSpiceModelLine() const
template <class T_symbol, class T_field>
bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, bool aResolve,
bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, std::vector<T_field>* aFields, bool aResolve,
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aDeviceType,
wxString* aModelType, wxString* aModelParams, wxString* aPinMap )
{
@ -1071,38 +1074,25 @@ bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, bool aResolve,
return units;
};
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 );
wxString value = GetFieldValue( aFields, VALUE_FIELD, aResolve );
std::vector<LIB_PIN*> pins = aSymbol.GetAllLibPins();
*aDeviceType = getFieldValue( DEVICE_TYPE_FIELD );
*aModelType = getFieldValue( TYPE_FIELD );
*aModelParams = getFieldValue( PARAMS_FIELD );
*aPinMap = getFieldValue( PINS_FIELD );
*aDeviceType = GetFieldValue( aFields, DEVICE_TYPE_FIELD, aResolve );
*aModelType = GetFieldValue( aFields, TYPE_FIELD, aResolve );
*aModelParams = GetFieldValue( aFields, PARAMS_FIELD, aResolve );
*aPinMap = GetFieldValue( aFields, PINS_FIELD, aResolve );
if( pins.size() != 2 )
return false;
if( aDeviceType->IsEmpty()
if( ( ( *aDeviceType == "R" || *aDeviceType == "L" || *aDeviceType == "C" )
&& aModelType->IsEmpty() )
||
( aDeviceType->IsEmpty()
&& aModelType->IsEmpty()
&& !value.IsEmpty()
&& ( prefix.StartsWith( "R" ) || prefix.StartsWith( "L" ) || prefix.StartsWith( "C" ) ) )
&& ( prefix.StartsWith( "R" ) || prefix.StartsWith( "L" ) || prefix.StartsWith( "C" ) ) ) )
{
if( aDeviceType->IsEmpty() )
*aDeviceType = prefix.Left( 1 );
@ -1123,7 +1113,7 @@ bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, bool aResolve,
wxString valueExponent( idealVal.GetMatch( value, 2 ) );
wxString valueFraction( idealVal.GetMatch( value, 6 ) );
if( valueMantissa.Contains( wxT( "." ) ) )
if( valueMantissa.Contains( wxT( "." ) ) || valueFraction.IsEmpty() )
{
aModelParams->Printf( wxT( "%s=\"%s%s\"" ),
prefix.Left(1).Lower(),
@ -1185,7 +1175,7 @@ bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, bool aResolve,
wxString valueExponent( sourceVal.GetMatch( value, 2 ) );
wxString valueFraction( sourceVal.GetMatch( value, 6 ) );
if( valueMantissa.Contains( wxT( "." ) ) )
if( valueMantissa.Contains( wxT( "." ) ) || valueFraction.IsEmpty() )
{
aModelParams->Printf( wxT( "dc=\"%s%s\"" ),
valueMantissa,
@ -1215,13 +1205,17 @@ bool SIM_MODEL::InferSimModel( T_symbol& aSymbol, bool aResolve,
}
template bool SIM_MODEL::InferSimModel<SCH_SYMBOL, SCH_FIELD>( SCH_SYMBOL& aSymbol, bool aResolve,
template bool SIM_MODEL::InferSimModel<SCH_SYMBOL, SCH_FIELD>( SCH_SYMBOL& aSymbol,
std::vector<SCH_FIELD>* aFields,
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,
template bool SIM_MODEL::InferSimModel<LIB_SYMBOL, LIB_FIELD>( LIB_SYMBOL& aSymbol,
std::vector<LIB_FIELD>* aFields,
bool aResolve,
SIM_VALUE_GRAMMAR::NOTATION aNotation,
wxString* aDeviceType,
wxString* aModelType,

View File

@ -415,7 +415,8 @@ public:
const std::vector<LIB_PIN*>& aPins );
template <typename T>
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName );
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName,
bool aResolve = true );
template <typename T>
static void SetFieldValue( std::vector<T>& aFields, const std::string& aFieldName,
@ -519,7 +520,7 @@ public:
virtual void SwitchSingleEndedDiff( bool aDiff ) { };
template <class T_symbol, class T_field>
static bool InferSimModel( T_symbol& aSymbol, bool aResolve,
static bool InferSimModel( T_symbol& aSymbol, std::vector<T_field>* aFields, bool aResolve,
SIM_VALUE_GRAMMAR::NOTATION aNotation, wxString* aDeviceType,
wxString* aModelType, wxString* aModelParams, wxString* aPinMap );

View File

@ -509,6 +509,8 @@ bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation
try
{
LOCALE_IO toggle;
m_value = std::stod( parseResult.significand ) * std::pow( 10, exponent );
}
catch( const std::invalid_argument& )