Remove most of SIM_VALUE in favour of good old wxString.

This allows us to save the user's intent, including units, formatting,
and crucially variable references.
This commit is contained in:
Jeff Young 2023-02-22 09:10:06 +00:00
parent 29f21cdde6
commit 68fe146861
29 changed files with 320 additions and 669 deletions

View File

@ -568,7 +568,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelParamsTab( SIM_MODEL* aMode
// This feature is called "autofill" and present only in certain models. Don't do it for // This feature is called "autofill" and present only in certain models. Don't do it for
// models that don't have it for performance reasons. // models that don't have it for performance reasons.
if( aModel->HasAutofill() ) if( aModel->HasAutofill() )
( *it )->SetValueFromString( param.value->ToString() ); ( *it )->SetValueFromString( param.value );
} }
} }

View File

@ -478,7 +478,7 @@ void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSym
if( auto rawSpiceModel = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model ) ) if( auto rawSpiceModel = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model ) )
{ {
int libParamIndex = static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB ); int libParamIndex = static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
wxString path = rawSpiceModel->GetParam( libParamIndex ).value->ToString(); wxString path = rawSpiceModel->GetParam( libParamIndex ).value;
if( !path.IsEmpty() ) if( !path.IsEmpty() )
m_rawIncludes.insert( path ); m_rawIncludes.insert( path );

View File

@ -717,7 +717,7 @@ void SIM_MODEL::AddParam( const PARAM::INFO& aInfo )
// Enums are initialized with their default values. // Enums are initialized with their default values.
if( aInfo.enumValues.size() >= 1 ) if( aInfo.enumValues.size() >= 1 )
m_params.back().value->FromString( aInfo.defaultValue ); m_params.back().value = aInfo.defaultValue;
} }
@ -790,7 +790,7 @@ void SIM_MODEL::SetPinSymbolPinNumber( const std::string& aPinName,
const SIM_MODEL::PARAM& SIM_MODEL::GetParam( unsigned aParamIndex ) const const SIM_MODEL::PARAM& SIM_MODEL::GetParam( unsigned aParamIndex ) const
{ {
if( m_baseModel && m_params.at( aParamIndex ).value->ToString() == "" ) if( m_baseModel && m_params.at( aParamIndex ).value == "" )
return m_baseModel->GetParam( aParamIndex ); return m_baseModel->GetParam( aParamIndex );
else else
return m_params.at( aParamIndex ); return m_params.at( aParamIndex );
@ -847,17 +847,16 @@ const SIM_MODEL::PARAM& SIM_MODEL::GetBaseParam( unsigned aParamIndex ) const
} }
void SIM_MODEL::SetParamValue( int aParamIndex, const SIM_VALUE& aValue ) void SIM_MODEL::doSetParamValue( int aParamIndex, const std::string& aValue )
{ {
*m_params.at( aParamIndex ).value = aValue; m_params.at( aParamIndex ).value = aValue;
} }
void SIM_MODEL::SetParamValue( int aParamIndex, const std::string& aValue, void SIM_MODEL::SetParamValue( int aParamIndex, const std::string& aValue,
SIM_VALUE::NOTATION aNotation ) SIM_VALUE::NOTATION aNotation )
{ {
const SIM_VALUE& value = *GetParam( aParamIndex ).value; doSetParamValue( aParamIndex, SIM_VALUE::Normalize( aValue, aNotation ) );
SetParamValue( aParamIndex, *SIM_VALUE::Create( value.GetType(), aValue, aNotation ) );
} }
@ -882,7 +881,7 @@ bool SIM_MODEL::HasOverrides() const
{ {
for( const PARAM& param : m_params ) for( const PARAM& param : m_params )
{ {
if( param.value->ToString() != "" ) if( param.value != "" )
return true; return true;
} }
@ -894,7 +893,7 @@ bool SIM_MODEL::HasNonInstanceOverrides() const
{ {
for( const PARAM& param : m_params ) for( const PARAM& param : m_params )
{ {
if( !param.info.isInstanceParam && param.value->ToString() != "" ) if( !param.info.isInstanceParam && param.value != "" )
return true; return true;
} }
@ -906,7 +905,7 @@ bool SIM_MODEL::HasSpiceNonInstanceOverrides() const
{ {
for( const PARAM& param : m_params ) for( const PARAM& param : m_params )
{ {
if( !param.info.isSpiceInstanceParam && param.value->ToString() != "" ) if( !param.info.isSpiceInstanceParam && param.value != "" )
return true; return true;
} }

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 CERN * Copyright (C) 2022 CERN
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -377,12 +377,11 @@ public:
} }
}; };
std::unique_ptr<SIM_VALUE> value; std::string value;
const INFO& info; const INFO& info;
PARAM( const INFO& aInfo ) PARAM( const INFO& aInfo ) :
: value( SIM_VALUE::Create( aInfo.type ) ), info( aInfo )
info( aInfo )
{} {}
}; };
@ -487,7 +486,6 @@ public:
const PARAM& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists. const PARAM& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists.
virtual void SetParamValue( int aParamIndex, const SIM_VALUE& aValue );
void SetParamValue( int aParamIndex, const std::string& aValue, void SetParamValue( int aParamIndex, const std::string& aValue,
SIM_VALUE::NOTATION aNotation = SIM_VALUE::NOTATION::SI ); SIM_VALUE::NOTATION aNotation = SIM_VALUE::NOTATION::SI );
void SetParamValue( const std::string& aParamName, const std::string& aValue, void SetParamValue( const std::string& aParamName, const std::string& aValue,
@ -532,6 +530,7 @@ protected:
void createPins( const std::vector<LIB_PIN*>& aSymbolPins ); void createPins( const std::vector<LIB_PIN*>& aSymbolPins );
virtual int doFindParam( const std::string& aParamName ) const; virtual int doFindParam( const std::string& aParamName ) const;
virtual void doSetParamValue( int aParamIndex, const std::string& aValue );
private: private:
template <typename T> template <typename T>

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -44,21 +44,21 @@ std::string SPICE_GENERATOR_BEHAVIORAL::ItemLine( const SPICE_ITEM& aItem ) cons
case SIM_MODEL::TYPE::L_BEHAVIORAL: case SIM_MODEL::TYPE::L_BEHAVIORAL:
{ {
SPICE_ITEM item = aItem; SPICE_ITEM item = aItem;
item.modelName = m_model.GetParam( 0 ).value->ToSpiceString(); item.modelName = SIM_VALUE::ToSpice( m_model.GetParam( 0 ).value );
return SPICE_GENERATOR::ItemLine( item ); return SPICE_GENERATOR::ItemLine( item );
} }
case SIM_MODEL::TYPE::V_BEHAVIORAL: case SIM_MODEL::TYPE::V_BEHAVIORAL:
{ {
SPICE_ITEM item = aItem; SPICE_ITEM item = aItem;
item.modelName = fmt::format( "V={}", m_model.GetParam( 0 ).value->ToSpiceString() ); item.modelName = fmt::format( "V={}", SIM_VALUE::ToSpice( m_model.GetParam( 0 ).value ) );
return SPICE_GENERATOR::ItemLine( item ); return SPICE_GENERATOR::ItemLine( item );
} }
case SIM_MODEL::TYPE::I_BEHAVIORAL: case SIM_MODEL::TYPE::I_BEHAVIORAL:
{ {
SPICE_ITEM item = aItem; SPICE_ITEM item = aItem;
item.modelName = fmt::format( "I={}", m_model.GetParam( 0 ).value->ToSpiceString() ); item.modelName = fmt::format( "I={}", SIM_VALUE::ToSpice( m_model.GetParam( 0 ).value ) );
return SPICE_GENERATOR::ItemLine( item ); return SPICE_GENERATOR::ItemLine( item );
} }

View File

@ -37,7 +37,7 @@ std::string SPICE_GENERATOR_IDEAL::ModelLine( const SPICE_ITEM& aItem ) const
std::string SPICE_GENERATOR_IDEAL::ItemLine( const SPICE_ITEM& aItem ) const std::string SPICE_GENERATOR_IDEAL::ItemLine( const SPICE_ITEM& aItem ) const
{ {
SPICE_ITEM item = aItem; SPICE_ITEM item = aItem;
item.modelName = m_model.GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE ); item.modelName = SIM_VALUE::ToSpice( m_model.GetParam( 0 ).value );
if( item.modelName != "" ) if( item.modelName != "" )
return SPICE_GENERATOR::ItemLine( item ); return SPICE_GENERATOR::ItemLine( item );
@ -46,12 +46,11 @@ std::string SPICE_GENERATOR_IDEAL::ItemLine( const SPICE_ITEM& aItem ) const
} }
std::string SPICE_GENERATOR_IDEAL::TunerCommand( const SPICE_ITEM& aItem, std::string SPICE_GENERATOR_IDEAL::TunerCommand( const SPICE_ITEM& aItem, double aValue ) const
const SIM_VALUE_FLOAT& aValue ) const
{ {
return fmt::format( "alter @{}={}", return fmt::format( "alter @{}={:g}",
aItem.model->SpiceGenerator().ItemName( aItem ), aItem.model->SpiceGenerator().ItemName( aItem ),
aValue.ToSpiceString() ); aValue );
} }

View File

@ -37,7 +37,7 @@ public:
std::string ModelLine( const SPICE_ITEM& aItem ) const override; std::string ModelLine( const SPICE_ITEM& aItem ) const override;
std::string ItemLine( const SPICE_ITEM& aItem ) const override; std::string ItemLine( const SPICE_ITEM& aItem ) const override;
std::string TunerCommand( const SPICE_ITEM& aItem, const SIM_VALUE_FLOAT& aValue ) const override; std::string TunerCommand( const SPICE_ITEM& aItem, double aValue ) const override;
}; };

View File

@ -111,18 +111,18 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
KIBIS_PARAMETER kparams; KIBIS_PARAMETER kparams;
if ( m_model.FindParam( "vcc" ) ) if ( m_model.FindParam( "vcc" ) )
kparams.SetCornerFromString( kparams.m_supply, m_model.FindParam( "vcc" )->value->ToString() ); kparams.SetCornerFromString( kparams.m_supply, m_model.FindParam( "vcc" )->value );
if ( m_model.FindParam( "rpin" ) ) if ( m_model.FindParam( "rpin" ) )
kparams.SetCornerFromString( kparams.m_Rpin, m_model.FindParam( "rpin" )->value->ToString() ); kparams.SetCornerFromString( kparams.m_Rpin, m_model.FindParam( "rpin" )->value );
if ( m_model.FindParam( "lpin" ) ) if ( m_model.FindParam( "lpin" ) )
kparams.SetCornerFromString( kparams.m_Lpin, m_model.FindParam( "lpin" )->value->ToString() ); kparams.SetCornerFromString( kparams.m_Lpin, m_model.FindParam( "lpin" )->value );
if ( m_model.FindParam( "cpin" ) ) if ( m_model.FindParam( "cpin" ) )
kparams.SetCornerFromString( kparams.m_Cpin, m_model.FindParam( "cpin" )->value->ToString() ); kparams.SetCornerFromString( kparams.m_Cpin, m_model.FindParam( "cpin" )->value );
//kparams.SetCornerFromString( kparams.m_Ccomp, FindParam( "ccomp" )->value->ToString() ); //kparams.SetCornerFromString( kparams.m_Ccomp, FindParam( "ccomp" )->value );
std::string result; std::string result;
@ -140,7 +140,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
std::string paramValue = ""; std::string paramValue = "";
if ( m_model.FindParam( "dc" ) ) if ( m_model.FindParam( "dc" ) )
paramValue = m_model.FindParam( "dc" )->value->ToString(); paramValue = m_model.FindParam( "dc" )->value;
if( paramValue == "hi-Z" ) if( paramValue == "hi-Z" )
{ {
@ -167,16 +167,16 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
KIBIS_WAVEFORM_RECTANGULAR* waveform = new KIBIS_WAVEFORM_RECTANGULAR( &kibis ); KIBIS_WAVEFORM_RECTANGULAR* waveform = new KIBIS_WAVEFORM_RECTANGULAR( &kibis );
if ( m_model.FindParam( "ton" ) ) if ( m_model.FindParam( "ton" ) )
waveform->m_ton = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "ton" )->value ).Get().value_or( 1 ); waveform->m_ton = SIM_VALUE::ToDouble( m_model.FindParam( "ton" )->value, 1 );
if ( m_model.FindParam( "toff" ) ) if ( m_model.FindParam( "toff" ) )
waveform->m_toff = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "toff" )->value ).Get().value_or( 1 ); waveform->m_toff = SIM_VALUE::ToDouble( m_model.FindParam( "toff" )->value, 1 );
if ( m_model.FindParam( "td" ) ) if ( m_model.FindParam( "td" ) )
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "td" )->value ).Get().value_or( 0 ); waveform->m_delay = SIM_VALUE::ToDouble( m_model.FindParam( "td" )->value, 0 );
if ( m_model.FindParam( "n" ) ) if ( m_model.FindParam( "n" ) )
waveform->m_cycles = static_cast<SIM_VALUE_INT&>( *m_model.FindParam( "n" )->value ).Get().value_or( 1 ); waveform->m_cycles = SIM_VALUE::ToInt( m_model.FindParam( "n" )->value, 1 );
kparams.m_waveform = waveform; kparams.m_waveform = waveform;
@ -192,13 +192,13 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
KIBIS_WAVEFORM_PRBS* waveform = new KIBIS_WAVEFORM_PRBS( &kibis ); KIBIS_WAVEFORM_PRBS* waveform = new KIBIS_WAVEFORM_PRBS( &kibis );
if ( m_model.FindParam( "f0" ) ) if ( m_model.FindParam( "f0" ) )
waveform->m_bitrate = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "f0" )->value ).Get().value_or( 0 ); waveform->m_bitrate = SIM_VALUE::ToDouble( m_model.FindParam( "f0" )->value, 0 );
if ( m_model.FindParam( "td" ) ) if ( m_model.FindParam( "td" ) )
waveform->m_delay = static_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "td" )->value ).Get().value_or( 0 ); waveform->m_delay = SIM_VALUE::ToDouble( m_model.FindParam( "td" )->value, 0 );
if ( m_model.FindParam( "n" ) ) if ( m_model.FindParam( "n" ) )
waveform->m_bits = static_cast<SIM_VALUE_INT&>( *m_model.FindParam( "n" )->value ).Get().value_or( 0 ); waveform->m_bits = SIM_VALUE::ToInt( m_model.FindParam( "n" )->value, 0 );
kparams.m_waveform = waveform; kparams.m_waveform = waveform;
@ -276,7 +276,7 @@ SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) :
const PARAM& param2 = param2refwrap.get(); const PARAM& param2 = param2refwrap.get();
if( param1.info.name == param2.info.name ) if( param1.info.name == param2.info.name )
*( param1.value ) = *( param2.value ); param1.value = param2.value;
} }
} }

View File

@ -30,7 +30,7 @@ std::string SPICE_GENERATOR_L_MUTUAL::ItemParams() const
std::string result; std::string result;
for( const SIM_MODEL::PARAM& param : GetInstanceParams() ) for( const SIM_MODEL::PARAM& param : GetInstanceParams() )
result.append( " " + param.value->ToSpiceString() ); result.append( " " + SIM_VALUE::ToSpice( param.value ) );
return result; return result;
} }

View File

@ -127,8 +127,7 @@ void SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const std::string& aParamName,
&& param.info.category != PARAM::CATEGORY::SUPERFLUOUS && param.info.category != PARAM::CATEGORY::SUPERFLUOUS
&& ( param.info.name == lowerParamName || param.info.name == lowerParamName + "_" ) ) && ( param.info.name == lowerParamName || param.info.name == lowerParamName + "_" ) )
{ {
const SIM_VALUE& value = *GetParam( ii ).value; SetParamValue( ii, aValue, aNotation );
SetParamValue( ii, *SIM_VALUE::Create( value.GetType(), aValue, aNotation ) );
return; return;
} }
} }
@ -151,8 +150,7 @@ void SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const std::string& aParamName,
if( param.info.id == ngspiceParamInfo.id if( param.info.id == ngspiceParamInfo.id
&& param.info.category != PARAM::CATEGORY::SUPERFLUOUS ) && param.info.category != PARAM::CATEGORY::SUPERFLUOUS )
{ {
const SIM_VALUE& value = *GetParam( ii ).value; SetParamValue( ii, aValue, aNotation );
SetParamValue( ii, *SIM_VALUE::Create( value.GetType(), aValue, aNotation ) );
return; return;
} }
} }

View File

@ -32,10 +32,10 @@ std::string SPICE_GENERATOR_R_POT::ModelLine( const SPICE_ITEM& aItem ) const
std::string position = ""; std::string position = "";
if ( m_model.FindParam( "r" ) ) if ( m_model.FindParam( "r" ) )
r = m_model.FindParam( "r" )->value->ToSpiceString(); r = SIM_VALUE::ToSpice( m_model.FindParam( "r" )->value );
if ( m_model.FindParam( "pos" ) ) if ( m_model.FindParam( "pos" ) )
position = m_model.FindParam( "pos" )->value->ToSpiceString(); position = SIM_VALUE::ToSpice( m_model.FindParam( "pos" )->value );
if( position != "" ) if( position != "" )
{ {
@ -47,11 +47,11 @@ std::string SPICE_GENERATOR_R_POT::ModelLine( const SPICE_ITEM& aItem ) const
} }
std::string SPICE_GENERATOR_R_POT::TunerCommand( const SPICE_ITEM& aItem, std::string SPICE_GENERATOR_R_POT::TunerCommand( const SPICE_ITEM& aItem, double aValue ) const
const SIM_VALUE_FLOAT& aValue ) const
{ {
return fmt::format( "altermod @{}[position]={}", return fmt::format( "altermod @{}[position]={:g}",
aItem.model->SpiceGenerator().ItemName( aItem ), aValue.ToSpiceString() ); aItem.model->SpiceGenerator().ItemName( aItem ),
aValue );
} }

View File

@ -35,7 +35,7 @@ public:
using SPICE_GENERATOR::SPICE_GENERATOR; using SPICE_GENERATOR::SPICE_GENERATOR;
std::string ModelLine( const SPICE_ITEM& aItem ) const override; std::string ModelLine( const SPICE_ITEM& aItem ) const override;
std::string TunerCommand( const SPICE_ITEM& aItem, const SIM_VALUE_FLOAT& aValue ) const override; std::string TunerCommand( const SPICE_ITEM& aItem, double aValue ) const override;
}; };

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -47,13 +47,12 @@ std::string SPICE_GENERATOR_RAW_SPICE::ModelLine( const SPICE_ITEM& aItem ) cons
std::string SPICE_GENERATOR_RAW_SPICE::ItemName( const SPICE_ITEM& aItem ) const std::string SPICE_GENERATOR_RAW_SPICE::ItemName( const SPICE_ITEM& aItem ) const
{ {
std::string elementType = m_model.GetParam( std::string type = m_model.GetParam( (int) SIM_MODEL_RAW_SPICE::SPICE_PARAM::TYPE ).value;
static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::TYPE ) ).value->ToString();
if( aItem.refName != "" && boost::starts_with( aItem.refName, elementType ) ) if( aItem.refName != "" && boost::starts_with( aItem.refName, type ) )
return aItem.refName; return aItem.refName;
else else
return fmt::format( "{}{}", elementType, aItem.refName ); return fmt::format( "{}{}", type, aItem.refName );
} }
@ -105,7 +104,7 @@ std::string SPICE_GENERATOR_RAW_SPICE::ItemParams() const
for( const SIM_MODEL::PARAM& param : GetInstanceParams() ) for( const SIM_MODEL::PARAM& param : GetInstanceParams() )
{ {
if( param.info.name == "model" ) if( param.info.name == "model" )
result.append( " " + param.value->ToString() ); result.append( " " + param.value );
} }
return result; return result;

View File

@ -67,7 +67,7 @@ std::string SIM_MODEL_SERIALIZER::GenerateType() const
std::string SIM_MODEL_SERIALIZER::GenerateValue() const std::string SIM_MODEL_SERIALIZER::GenerateValue() const
{ {
const SIM_MODEL::PARAM& param = m_model.GetParamOverride( 0 ); const SIM_MODEL::PARAM& param = m_model.GetParamOverride( 0 );
std::string result = param.value->ToString(); std::string result = param.value;
if( result == "" ) if( result == "" )
result = m_model.GetDeviceInfo().fieldValue; result = m_model.GetDeviceInfo().fieldValue;
@ -88,14 +88,14 @@ std::string SIM_MODEL_SERIALIZER::GenerateParams() const
const SIM_MODEL::PARAM& param = m_model.GetParamOverride( i ); const SIM_MODEL::PARAM& param = m_model.GetParamOverride( i );
if( param.value->ToString() == "" if( param.value == ""
&& !( i == 0 && m_model.HasPrimaryValue() && !m_model.IsStoredInValue() ) ) && !( i == 0 && m_model.HasPrimaryValue() && !m_model.IsStoredInValue() ) )
{ {
continue; continue;
} }
// If the parameter is an enum and the value is default, don't write anything. // If the parameter is an enum and the value is default, don't write anything.
if( param.info.enumValues.size() >= 1 && param.value->ToString() == param.info.defaultValue ) if( param.info.enumValues.size() >= 1 && param.value == param.info.defaultValue )
continue; continue;
std::string paramValuePair = generateParamValuePair( param ); std::string paramValuePair = generateParamValuePair( param );
@ -298,7 +298,7 @@ std::string SIM_MODEL_SERIALIZER::generateParamValuePair( const SIM_MODEL::PARAM
if( boost::ends_with( aParam.info.name, "_" ) ) if( boost::ends_with( aParam.info.name, "_" ) )
name = aParam.info.name.substr( 0, aParam.info.name.length() - 1 ); name = aParam.info.name.substr( 0, aParam.info.name.length() - 1 );
std::string value = aParam.value->ToString(); std::string value = aParam.value;
if( value == "" || value.find( ' ' ) != std::string::npos ) if( value == "" || value.find( ' ' ) != std::string::npos )
value = fmt::format( "\"{}\"", value ); value = fmt::format( "\"{}\"", value );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -53,9 +53,9 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
std::string dc = ""; std::string dc = "";
if( m_model.FindParam( "ac" ) ) if( m_model.FindParam( "ac" ) )
ac = m_model.FindParam( "ac" )->value->ToSpiceString(); ac = SIM_VALUE::ToSpice( m_model.FindParam( "ac" )->value );
if( m_model.FindParam( "dc" ) ) if( m_model.FindParam( "dc" ) )
dc = m_model.FindParam( "dc" )->value->ToSpiceString(); dc = SIM_VALUE::ToSpice( m_model.FindParam( "dc" )->value );
bool emptyLine = true; bool emptyLine = true;
item.modelName = ""; item.modelName = "";
@ -82,8 +82,7 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
case SIM_MODEL::TYPE::V_PWL: case SIM_MODEL::TYPE::V_PWL:
case SIM_MODEL::TYPE::I_PWL: case SIM_MODEL::TYPE::I_PWL:
{ {
tao::pegtl::string_input<> in( m_model.GetParam( 0 ).value->ToString(), tao::pegtl::string_input<> in( m_model.GetParam( 0 ).value, "from_content" );
"from_content" );
std::unique_ptr<tao::pegtl::parse_tree::node> root; std::unique_ptr<tao::pegtl::parse_tree::node> root;
try try
@ -104,9 +103,7 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
if( node->is_type<SIM_MODEL_SOURCE_PARSER::number<SIM_VALUE::TYPE_FLOAT, if( node->is_type<SIM_MODEL_SOURCE_PARSER::number<SIM_VALUE::TYPE_FLOAT,
SIM_VALUE::NOTATION::SI>>() ) SIM_VALUE::NOTATION::SI>>() )
{ {
std::unique_ptr<SIM_VALUE> value = SIM_VALUE::Create( SIM_VALUE::TYPE_FLOAT, args.append( SIM_VALUE::ToSpice( node->string() ) + " " );
node->string() );
args.append( value->ToString( SIM_VALUE::NOTATION::SPICE ) + " " );
} }
} }
} }
@ -143,16 +140,17 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
case SIM_MODEL::TYPE::V_RANDUNIFORM: case SIM_MODEL::TYPE::V_RANDUNIFORM:
case SIM_MODEL::TYPE::I_RANDUNIFORM: case SIM_MODEL::TYPE::I_RANDUNIFORM:
{ {
/* JEY TODO
args.append( "1 " ); args.append( "1 " );
args.append( getParamValueString( "dt", "0" ) + " " ); args.append( getParamValueString( "dt", "0" ) + " " );
args.append( getParamValueString( "td", "0" ) + " " ); args.append( getParamValueString( "td", "0" ) + " " );
SIM_VALUE_FLOAT min = dynamic_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "max" )->value ); SIM_VALUE_FLOAT min = dynamic_cast<SIM_VALUE_FLOAT&>( m_model.FindParam( "max" )->value );
if( !min.ToString().empty() ) if( !min.ToString().empty() )
min.FromString( "0" ); min.FromString( "0" );
SIM_VALUE_FLOAT max = dynamic_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "min" )->value ); SIM_VALUE_FLOAT max = dynamic_cast<SIM_VALUE_FLOAT&>( m_model.FindParam( "min" )->value );
if( !max.ToString().empty() ) if( !max.ToString().empty() )
max.FromString( "0" ); max.FromString( "0" );
@ -162,7 +160,7 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
args.append( range.ToSpiceString() + " " ); args.append( range.ToSpiceString() + " " );
args.append( offset.ToSpiceString() + " " ); args.append( offset.ToSpiceString() + " " );
*/
break; break;
} }
@ -196,7 +194,7 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
default: default:
for( const SIM_MODEL::PARAM& param : m_model.GetParams() ) for( const SIM_MODEL::PARAM& param : m_model.GetParams() )
{ {
std::string argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE ); std::string argStr = SIM_VALUE::ToSpice( param.value );
if( argStr != "" ) if( argStr != "" )
args.append( argStr + " " ); args.append( argStr + " " );
@ -214,7 +212,7 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
std::string ph = ""; std::string ph = "";
if( m_model.FindParam( "ph" ) ) if( m_model.FindParam( "ph" ) )
ph = m_model.FindParam( "ph" )->value->ToSpiceString(); ph = SIM_VALUE::ToSpice( m_model.FindParam( "ph" )->value );
emptyLine = false; emptyLine = false;
item.modelName += fmt::format( "AC {} {}", ac, ph ); item.modelName += fmt::format( "AC {} {}", ac, ph );
@ -222,7 +220,7 @@ std::string SPICE_GENERATOR_SOURCE::ItemLine( const SPICE_ITEM& aItem ) const
if( emptyLine ) if( emptyLine )
{ {
item.modelName = m_model.GetParam( 0 ).value->ToSpiceString(); item.modelName = SIM_VALUE::ToSpice( m_model.GetParam( 0 ).value );
} }
return SPICE_GENERATOR::ItemLine( item ); return SPICE_GENERATOR::ItemLine( item );
@ -235,7 +233,7 @@ std::string SPICE_GENERATOR_SOURCE::getParamValueString( const std::string& aPar
std::string result = ""; std::string result = "";
if ( m_model.FindParam( aParamName ) ) if ( m_model.FindParam( aParamName ) )
result = m_model.FindParam( aParamName )->value->ToSpiceString(); result = SIM_VALUE::ToSpice( m_model.FindParam( aParamName )->value );
if( result == "" ) if( result == "" )
result = aDefaultValue; result = aDefaultValue;
@ -253,32 +251,32 @@ SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) :
} }
void SIM_MODEL_SOURCE::SetParamValue( int aParamIndex, const SIM_VALUE& aValue ) void SIM_MODEL_SOURCE::doSetParamValue( int aParamIndex, const std::string& aValue )
{ {
// Sources are special. All preceding parameter values must be filled. If they are not, fill // Sources are special. All preceding parameter values must be filled. If they are not, fill
// them out automatically. If a value is nulled, delete everything after it. // them out automatically. If a value is nulled, delete everything after it.
if( aValue.ToString().empty() ) if( aValue.empty() )
{ {
for( int paramIndex = static_cast<int>( aParamIndex ); for( int paramIndex = static_cast<int>( aParamIndex );
paramIndex < GetParamCount(); paramIndex < GetParamCount();
++paramIndex ) ++paramIndex )
{ {
m_params.at( aParamIndex ).value->FromString( "" ); m_params.at( aParamIndex ).value = "";
} }
} }
else else
{ {
for( int paramIndex = 0; paramIndex < aParamIndex; ++paramIndex ) for( int paramIndex = 0; paramIndex < aParamIndex; ++paramIndex )
{ {
if( GetParam( paramIndex ).value->ToString() == "" ) if( GetParam( paramIndex ).value == "" )
{ {
m_params.at( aParamIndex ).value->FromString( "0" ); m_params.at( aParamIndex ).value = "0";
SIM_MODEL::SetParamValue( paramIndex, "0" ); SIM_MODEL::SetParamValue( paramIndex, "0" );
} }
} }
} }
return SIM_MODEL::SetParamValue( aParamIndex, aValue ); return SIM_MODEL::doSetParamValue( aParamIndex, aValue );
} }

View File

@ -71,13 +71,14 @@ class SIM_MODEL_SOURCE : public SIM_MODEL
public: public:
SIM_MODEL_SOURCE( TYPE aType ); SIM_MODEL_SOURCE( TYPE aType );
void SetParamValue( int aParamIndex, const SIM_VALUE& aValue ) override;
bool HasAutofill() const override { return true; } bool HasAutofill() const override { return true; }
bool HasPrimaryValue() const override { return GetType() == TYPE::V || GetType() == TYPE::I; } bool HasPrimaryValue() const override { return GetType() == TYPE::V || GetType() == TYPE::I; }
std::vector<std::string> GetPinNames() const override { return { "+", "-" }; } std::vector<std::string> GetPinNames() const override { return { "+", "-" }; }
protected:
void doSetParamValue( int aParamIndex, const std::string& aValue ) override;
private: private:
static const std::vector<PARAM::INFO>& makeParamInfos( TYPE aType ); static const std::vector<PARAM::INFO>& makeParamInfos( TYPE aType );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -93,12 +93,12 @@ SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr<SPICE_GENERATOR> a
} }
void SIM_MODEL_SPICE::SetParamValue( int aParamIndex, const SIM_VALUE& aValue ) void SIM_MODEL_SPICE::doSetParamValue( int aParamIndex, const std::string& aValue )
{ {
if( m_spiceCode != "" ) if( m_spiceCode != "" )
THROW_IO_ERROR( "Could not change model parameters: library models are immutable" ); THROW_IO_ERROR( "Could not change model parameters: library models are immutable" );
SIM_MODEL::SetParamValue( aParamIndex, aValue ); SIM_MODEL::doSetParamValue( aParamIndex, aValue );
} }

View File

@ -58,7 +58,7 @@ public:
std::unique_ptr<SPICE_MODEL_PARSER> aSpiceModelParser ); std::unique_ptr<SPICE_MODEL_PARSER> aSpiceModelParser );
protected: protected:
void SetParamValue( int aParamIndex, const SIM_VALUE& aValue ) override; void doSetParamValue( int aParamIndex, const std::string& aValue ) override;
virtual void SetParamFromSpiceCode( const std::string& aParamName, virtual void SetParamFromSpiceCode( const std::string& aParamName,
const std::string& aParamValue, const std::string& aParamValue,

View File

@ -69,7 +69,7 @@ std::string SPICE_GENERATOR_SWITCH::ItemParams() const
for( const SIM_MODEL::PARAM& param : GetInstanceParams() ) for( const SIM_MODEL::PARAM& param : GetInstanceParams() )
{ {
// The only instance param is "ic", which is positional. // The only instance param is "ic", which is positional.
std::string value = param.value->ToSpiceString(); std::string value = param.value;
if( value != "none" ) if( value != "none" )
result.append( value ); result.append( value );

View File

@ -31,37 +31,34 @@ using PARAM = SIM_MODEL::PARAM;
std::string SPICE_GENERATOR_TLINE::ModelLine( const SPICE_ITEM& aItem ) const std::string SPICE_GENERATOR_TLINE::ModelLine( const SPICE_ITEM& aItem ) const
{ {
std::string r="0" , l="0", g="0", c="0", len="1"; std::string r="0", l="0", g="0", c="0", len="1";
switch( m_model.GetType() ) switch( m_model.GetType() )
{ {
case SIM_MODEL::TYPE::TLINE_Z0: case SIM_MODEL::TYPE::TLINE_Z0:
{ {
auto z0 = static_cast<const SIM_VALUE_FLOAT&>( *m_model.FindParam( "z0" )->value ); double z0 = SIM_VALUE::ToDouble( m_model.FindParam( "z0" )->value );
auto td = static_cast<const SIM_VALUE_FLOAT&>( *m_model.FindParam( "td" )->value ); double td = SIM_VALUE::ToDouble( m_model.FindParam( "td" )->value );
if( !z0.ToString().empty() || !td.ToString().empty() ) if( isnan( z0 ) || isnan( td ) )
return fmt::format( ".model {} LTRA()\n", aItem.modelName ); return fmt::format( ".model {} LTRA()\n", aItem.modelName );
r = SIM_VALUE_FLOAT( 0 ).ToSpiceString(); l = fmt::format( "{:g}", td * z0 );
l = ( td * z0 ).ToSpiceString(); c = fmt::format( "{:g}", td / z0 );
g = SIM_VALUE_FLOAT( 0 ).ToSpiceString();
c = ( td / z0 ).ToSpiceString();
len = SIM_VALUE_FLOAT( 1 ).ToSpiceString();
break; break;
} }
case SIM_MODEL::TYPE::TLINE_RLGC: case SIM_MODEL::TYPE::TLINE_RLGC:
{ {
if( m_model.FindParam( "r" ) ) if( m_model.FindParam( "r" ) )
r = m_model.FindParam( "r" )->value->ToSpiceString(); r = SIM_VALUE::ToSpice( m_model.FindParam( "r" )->value );
if( m_model.FindParam( "l" ) ) if( m_model.FindParam( "l" ) )
l = m_model.FindParam( "l" )->value->ToSpiceString(); l = SIM_VALUE::ToSpice( m_model.FindParam( "l" )->value );
if( m_model.FindParam( "g" ) ) if( m_model.FindParam( "g" ) )
g = m_model.FindParam( "g" )->value->ToSpiceString(); g = SIM_VALUE::ToSpice( m_model.FindParam( "g" )->value );
if( m_model.FindParam( "c" ) ) if( m_model.FindParam( "c" ) )
c = m_model.FindParam( "c" )->value->ToSpiceString(); c = SIM_VALUE::ToSpice( m_model.FindParam( "c" )->value );
if( m_model.FindParam( "len" ) ) if( m_model.FindParam( "len" ) )
len = m_model.FindParam( "len" )->value->ToSpiceString(); len = SIM_VALUE::ToSpice( m_model.FindParam( "len" )->value );
break; break;
} }
default: default:

View File

@ -1735,7 +1735,7 @@ void SIM_PLOT_FRAME::applyTuners()
continue; continue;
} }
SIM_VALUE_FLOAT floatVal( tuner->GetValue().ToDouble() ); double floatVal = tuner->GetValue().ToDouble();
m_simulator->Command( item->model->SpiceGenerator().TunerCommand( *item, floatVal ) ); m_simulator->Command( item->model->SpiceGenerator().TunerCommand( *item, floatVal ) );
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -52,11 +52,8 @@ SIM_BOOL_PROPERTY::SIM_BOOL_PROPERTY( const wxString& aLabel, const wxString& aN
wxBoolProperty( aLabel, aName ), wxBoolProperty( aLabel, aName ),
SIM_PROPERTY( aModel, aParamIndex ) SIM_PROPERTY( aModel, aParamIndex )
{ {
auto simValue = dynamic_cast<SIM_VALUE_INST<bool>*>( m_model.GetParam( m_paramIndex ).value.get() ); std::string value = m_model.GetParam( m_paramIndex ).value;
SetValue( value == "1" );
wxCHECK( simValue, /*void*/ );
SetValue( *simValue == true );
} }
@ -73,14 +70,7 @@ void SIM_BOOL_PROPERTY::OnSetValue()
if( m_disabled ) if( m_disabled )
return; return;
auto simValue = dynamic_cast<SIM_VALUE_INST<bool>*>( m_model.GetParam( m_paramIndex ).value.get() ); m_model.SetParamValue( m_paramIndex, m_value.GetBool() ? "1" : "0" );
wxCHECK( simValue, /*void*/ );
if( m_model.GetBaseModel() && *simValue == m_value.GetBool() )
m_model.SetParamValue( m_paramIndex, "" );
else
m_model.SetParamValue( m_paramIndex, m_value.GetBool() ? "1" : "0" );
} }
@ -93,7 +83,7 @@ SIM_STRING_PROPERTY::SIM_STRING_PROPERTY( const wxString& aLabel, const wxString
m_valueType( aValueType ), m_valueType( aValueType ),
m_notation( aNotation ) m_notation( aNotation )
{ {
SetValueFromString( GetParam().value->ToString() ); SetValueFromString( GetParam().value );
} }
@ -176,7 +166,7 @@ bool SIM_STRING_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aT
text = aText; text = aText;
m_model.SetParamValue( m_paramIndex, std::string( text.ToUTF8() ) ); m_model.SetParamValue( m_paramIndex, std::string( text.ToUTF8() ) );
aVariant = GetParam().value->ToString(); aVariant = GetParam().value;
return true; return true;
} }
@ -201,7 +191,7 @@ SIM_ENUM_PROPERTY::SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aN
{ {
for( int ii = 0; ii < (int) GetParam().info.enumValues.size(); ++ii ) for( int ii = 0; ii < (int) GetParam().info.enumValues.size(); ++ii )
{ {
if( GetParam().info.enumValues[ii] == GetParam().value->ToString() ) if( GetParam().info.enumValues[ii] == GetParam().value )
{ {
SetValue( ii ); SetValue( ii );
return; return;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -28,6 +28,7 @@
#include <locale_io.h> #include <locale_io.h>
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
#include <fmt/core.h> #include <fmt/core.h>
#include <math/util.h>
#define CALL_INSTANCE( ValueType, Notation, func, ... ) \ #define CALL_INSTANCE( ValueType, Notation, func, ... ) \
@ -176,8 +177,8 @@ static inline void handleNodeForParse( tao::pegtl::parse_tree::node& aNode,
} }
else if( aNode.is_type<SIM_VALUE_PARSER::unitPrefix<ValueType, Notation>>() ) else if( aNode.is_type<SIM_VALUE_PARSER::unitPrefix<ValueType, Notation>>() )
{ {
aParseResult.unitPrefixExponent = aParseResult.unitPrefixExponent = SIM_VALUE_PARSER::UnitPrefixToExponent( aNode.string(),
SIM_VALUE_PARSER::UnitPrefixToExponent( aNode.string(), Notation ); Notation );
aParseResult.isEmpty = false; aParseResult.isEmpty = false;
} }
else else
@ -358,364 +359,82 @@ std::string SIM_VALUE_PARSER::ExponentToUnitPrefix( double aExponent, int& aExpo
} }
std::unique_ptr<SIM_VALUE> SIM_VALUE::Create( TYPE aType, const std::string& aString, std::string SIM_VALUE::ConvertNotation( const std::string& aString, NOTATION aFromNotation,
NOTATION aNotation ) NOTATION aToNotation )
{
std::unique_ptr<SIM_VALUE> value = SIM_VALUE::Create( aType );
value->FromString( aString, aNotation );
return value;
}
std::unique_ptr<SIM_VALUE> SIM_VALUE::Create( TYPE aType )
{
switch( aType )
{
case TYPE_BOOL: return std::make_unique<SIM_VALUE_BOOL>();
case TYPE_INT: return std::make_unique<SIM_VALUE_INT>();
case TYPE_FLOAT: return std::make_unique<SIM_VALUE_FLOAT>();
case TYPE_COMPLEX: return std::make_unique<SIM_VALUE_COMPLEX>();
case TYPE_STRING: return std::make_unique<SIM_VALUE_STRING>();
case TYPE_BOOL_VECTOR: return std::make_unique<SIM_VALUE_BOOL>();
case TYPE_INT_VECTOR: return std::make_unique<SIM_VALUE_INT>();
case TYPE_FLOAT_VECTOR: return std::make_unique<SIM_VALUE_FLOAT>();
case TYPE_COMPLEX_VECTOR: return std::make_unique<SIM_VALUE_COMPLEX>();
}
wxFAIL_MSG( _( "Unknown SIM_VALUE type" ) );
return nullptr;
}
SIM_VALUE& SIM_VALUE::operator=( const std::string& aString )
{
FromString( aString );
return *this;
}
bool SIM_VALUE::operator!=( const SIM_VALUE& aOther ) const
{
return !( *this == aOther );
}
template <typename T>
SIM_VALUE_INST<T>::SIM_VALUE_INST( const T& aValue ) : m_value( aValue )
{
}
template SIM_VALUE_BOOL::SIM_VALUE_INST( const bool& aValue );
template SIM_VALUE_INT::SIM_VALUE_INST( const int& aValue );
template SIM_VALUE_FLOAT::SIM_VALUE_INST( const double& aValue );
template SIM_VALUE_COMPLEX::SIM_VALUE_INST( const std::complex<double>& aValue );
template SIM_VALUE_STRING::SIM_VALUE_INST( const std::string& aValue );
template <> SIM_VALUE::TYPE SIM_VALUE_BOOL::GetType() const { return TYPE_BOOL; }
template <> SIM_VALUE::TYPE SIM_VALUE_INT::GetType() const { return TYPE_INT; }
template <> SIM_VALUE::TYPE SIM_VALUE_FLOAT::GetType() const { return TYPE_FLOAT; }
template <> SIM_VALUE::TYPE SIM_VALUE_COMPLEX::GetType() const { return TYPE_FLOAT; }
template <> SIM_VALUE::TYPE SIM_VALUE_STRING::GetType() const { return TYPE_STRING; }
// TODO
/*template <> SIM_VALUE::TYPE SIM_VALUE_BOOL_VECTOR::GetType() const { return TYPE_BOOL; }
template <> SIM_VALUE::TYPE SIM_VALUE_INT_VECTOR::GetType() const { return TYPE_INT; }
template <> SIM_VALUE::TYPE SIM_VALUE_FLOAT_VECTOR::GetType() const { return TYPE_FLOAT; }
template <> SIM_VALUE::TYPE SIM_VALUE_COMPLEX_VECTOR::GetType() const { return TYPE_COMPLEX; }*/
template <>
bool SIM_VALUE_BOOL::FromString( const std::string& aString, NOTATION aNotation )
{
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
m_value = std::nullopt;
if( !parseResult.isOk )
return false;
if( parseResult.isEmpty )
return true;
if( !parseResult.intPart
|| ( *parseResult.intPart != 0 && *parseResult.intPart != 1 )
|| parseResult.fracPart
|| parseResult.exponent
|| parseResult.unitPrefixExponent )
{
return false;
}
m_value = *parseResult.intPart;
return true;
}
template <>
bool SIM_VALUE_INT::FromString( const std::string& aString, NOTATION aNotation )
{
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
m_value = std::nullopt;
if( !parseResult.isOk )
return false;
if( parseResult.isEmpty )
return true;
if( !parseResult.intPart || ( parseResult.fracPart && *parseResult.fracPart != 0 ) )
return false;
int exponent = parseResult.exponent ? *parseResult.exponent : 0;
exponent += parseResult.unitPrefixExponent ? *parseResult.unitPrefixExponent : 0;
m_value = static_cast<double>( *parseResult.intPart ) * std::pow( 10, exponent );
return true;
}
template <>
bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation )
{ {
wxString buf( aString ); wxString buf( aString );
buf.Replace( ',', '.' );
// Convert any entered decimal point separators to the one our PEGTL grammar expects
buf.Replace( wxT( "," ), wxT( "." ) );
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( buf.ToStdString(), SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( buf.ToStdString(),
aNotation ); aFromNotation );
m_value = std::nullopt;
if( !parseResult.isOk ) if( parseResult.isOk && !parseResult.isEmpty && !parseResult.significand.empty() )
return false;
if( parseResult.isEmpty )
return true;
// Single dot should be allowed in fields.
// TODO: disallow single dot in models.
if( parseResult.significand.empty() || parseResult.significand == "." )
return false;
int exponent = parseResult.exponent ? *parseResult.exponent : 0;
exponent += parseResult.unitPrefixExponent ? *parseResult.unitPrefixExponent : 0;
try
{ {
LOCALE_IO toggle; int exponent = parseResult.exponent ? *parseResult.exponent : 0;
exponent += parseResult.unitPrefixExponent ? *parseResult.unitPrefixExponent : 0;
m_value = std::stod( parseResult.significand ) * std::pow( 10, exponent ); try
}
catch( const std::invalid_argument& )
{
return false;
}
return true;
}
template <>
bool SIM_VALUE_COMPLEX::FromString( const std::string& aString, NOTATION aNotation )
{
// TODO
/*LOCALE_IO toggle;
double value = 0;
if( !aString.ToDouble( &value ) )
throw KI_PARAM_ERROR( _( "Invalid complex sim value string" ) );
m_value = value;*/
return true;
}
template <>
bool SIM_VALUE_STRING::FromString( const std::string& aString, NOTATION aNotation )
{
m_value = aString;
return true;
}
template <typename T>
std::string SIM_VALUE_INST<T>::ToString( NOTATION aNotation ) const
{
static_assert( std::is_same<T, std::vector<T>>::value );
std::string string;
for( auto it = m_value.cbegin(); it != m_value.cend(); it++ )
{
string += SIM_VALUE_INST<T>( *it ).ToString();
string += ",";
}
return string;
}
template <>
std::string SIM_VALUE_BOOL::ToString( NOTATION aNotation ) const
{
if( m_value )
return fmt::format( "{:d}", *m_value );
return "";
}
template <>
std::string SIM_VALUE_INT::ToString( NOTATION aNotation ) const
{
if( m_value )
{
int value = std::abs( *m_value );
int exponent = 0;
while( value != 0 && value % 1000 == 0 )
{ {
exponent += 3; LOCALE_IO toggle;
value /= 1000; int expReduction = 0;
std::string prefix = SIM_VALUE_PARSER::ExponentToUnitPrefix( exponent, expReduction,
aToNotation );
exponent -= expReduction;
return fmt::format( "{:g}{}",
std::stod( parseResult.significand ) * std::pow( 10, exponent ),
prefix );
}
catch( const std::invalid_argument& )
{
// best efforts
} }
int dummy = 0;
std::string prefix = SIM_VALUE_PARSER::ExponentToUnitPrefix( (double) exponent, dummy,
aNotation );
return fmt::format( "{:d}{:s}", value, prefix );
} }
return ""; return aString;
} }
template <> double SIM_VALUE::ToDouble( const std::string& aString, double aDefault )
std::string SIM_VALUE_FLOAT::ToString( NOTATION aNotation ) const
{ {
if( m_value ) SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, NOTATION::SI );
if( parseResult.isOk && !parseResult.isEmpty && !parseResult.significand.empty() )
{ {
double exponent = std::log10( std::abs( *m_value ) ); try
int reductionExponent = 0; {
LOCALE_IO toggle;
int exponent = parseResult.exponent ? *parseResult.exponent : 0;
std::string prefix = SIM_VALUE_PARSER::ExponentToUnitPrefix( exponent, reductionExponent, exponent += parseResult.unitPrefixExponent ? *parseResult.unitPrefixExponent : 0;
aNotation );
double reducedValue = *m_value / std::pow( 10, reductionExponent );
return fmt::format( "{:g}{}", reducedValue, prefix ); return std::stod( parseResult.significand ) * std::pow( 10, exponent );
}
catch( const std::invalid_argument& )
{
// best efforts
}
} }
else
return ""; return aDefault;
} }
template <> int SIM_VALUE::ToInt( const std::string& aString, int aDefault )
std::string SIM_VALUE_COMPLEX::ToString( NOTATION aNotation ) const
{ {
if( m_value ) SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, NOTATION::SI );
return fmt::format( "{:g}+{:g}i", m_value->real(), m_value->imag() );
return ""; if( parseResult.isOk
&& !parseResult.isEmpty
&& parseResult.intPart
&& ( !parseResult.fracPart || *parseResult.fracPart == 0 ) )
{
int exponent = parseResult.exponent ? *parseResult.exponent : 0;
exponent += parseResult.unitPrefixExponent ? *parseResult.unitPrefixExponent : 0;
if( exponent >= 0 )
return (int) *parseResult.intPart * (int) std::pow( 10, exponent );
}
return aDefault;
} }
template <>
std::string SIM_VALUE_STRING::ToString( NOTATION aNotation ) const
{
if( m_value )
return *m_value;
return ""; // Empty string is completely equivalent to null string.
}
template <typename T>
SIM_VALUE_INST<T>& SIM_VALUE_INST<T>::operator=( const SIM_VALUE& aOther )
{
auto other = dynamic_cast<const SIM_VALUE_INST<T>*>( &aOther );
m_value = other->m_value;
return *this;
}
template <typename T>
bool SIM_VALUE_INST<T>::operator==( const T& aOther ) const
{
return m_value == aOther;
}
template <>
bool SIM_VALUE_BOOL::operator==( const bool& aOther ) const
{
// Note that we take nullopt as the same as false here.
if( !m_value )
return false == aOther;
return m_value == aOther;
}
template bool SIM_VALUE_INT::operator==( const int& aOther ) const;
template bool SIM_VALUE_FLOAT::operator==( const double& aOther ) const;
template bool SIM_VALUE_COMPLEX::operator==( const std::complex<double>& aOther ) const;
template bool SIM_VALUE_STRING::operator==( const std::string& aOther ) const;
template <typename T>
bool SIM_VALUE_INST<T>::operator==( const SIM_VALUE& aOther ) const
{
const SIM_VALUE_INST<T>* otherValue = dynamic_cast<const SIM_VALUE_INST<T>*>( &aOther );
if( otherValue )
return m_value == otherValue->m_value;
return false;
}
template <typename T>
SIM_VALUE_INST<T> operator+( const SIM_VALUE_INST<T>& aLeft, const SIM_VALUE_INST<T>& aRight )
{
return SIM_VALUE_INST( aLeft.m_value.value() + aRight.m_value.value() );
}
template SIM_VALUE_INT operator+( const SIM_VALUE_INT& aLeft,
const SIM_VALUE_INT& aRight );
template SIM_VALUE_FLOAT operator+( const SIM_VALUE_FLOAT& aLeft,
const SIM_VALUE_FLOAT& aRight );
template <typename T>
SIM_VALUE_INST<T> operator-( const SIM_VALUE_INST<T>& aLeft, const SIM_VALUE_INST<T>& aRight )
{
return SIM_VALUE_INST( aLeft.m_value.value() - aRight.m_value.value() );
}
template SIM_VALUE_INT operator-( const SIM_VALUE_INT& aLeft,
const SIM_VALUE_INT& aRight );
template SIM_VALUE_FLOAT operator-( const SIM_VALUE_FLOAT& aLeft,
const SIM_VALUE_FLOAT& aRight );
template <typename T>
SIM_VALUE_INST<T> operator*( const SIM_VALUE_INST<T>& aLeft, const SIM_VALUE_INST<T>& aRight )
{
return SIM_VALUE_INST( aLeft.m_value.value() * aRight.m_value.value() );
}
template SIM_VALUE_INT operator*( const SIM_VALUE_INT& aLeft,
const SIM_VALUE_INT& aRight );
template SIM_VALUE_FLOAT operator*( const SIM_VALUE_FLOAT& aLeft,
const SIM_VALUE_FLOAT& aRight );
template <typename T>
SIM_VALUE_INST<T> operator/( const SIM_VALUE_INST<T>& aLeft, const SIM_VALUE_INST<T>& aRight )
{
return SIM_VALUE_INST( aLeft.m_value.value() / aRight.m_value.value() );
}
template SIM_VALUE_INT operator/( const SIM_VALUE_INT& aLeft,
const SIM_VALUE_INT& aRight );
template SIM_VALUE_FLOAT operator/( const SIM_VALUE_FLOAT& aLeft,
const SIM_VALUE_FLOAT& aRight );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -76,75 +76,26 @@ public:
TYPE_COMPLEX_VECTOR TYPE_COMPLEX_VECTOR
}; };
static std::unique_ptr<SIM_VALUE> Create( TYPE aType, const std::string& aString, static std::string ConvertNotation( const std::string& aString, NOTATION aFromNotation,
NOTATION aNotation = NOTATION::SI ); NOTATION aToNotation );
static std::unique_ptr<SIM_VALUE> Create( TYPE aType );
virtual ~SIM_VALUE() = default; static std::string Normalize( const std::string& aString, NOTATION aNotation )
SIM_VALUE() = default; {
// Note: also converts decimal separators to '.'
return ConvertNotation( aString, aNotation, NOTATION::SI );
}
virtual TYPE GetType() const = 0; static std::string ToSpice( const std::string& aString )
{
return ConvertNotation( aString, NOTATION::SI, NOTATION::SPICE );
}
SIM_VALUE& operator=( const std::string& aString ); static double ToDouble( const std::string& aString, double aDefault = NAN );
virtual SIM_VALUE& operator=( const SIM_VALUE& aValue ) = 0;
virtual bool operator==( const SIM_VALUE& aOther ) const = 0;
bool operator!=( const SIM_VALUE& aOther ) const;
virtual bool FromString( const std::string& aString, NOTATION aNotation = NOTATION::SI ) = 0; static int ToInt( const std::string& aString, int aDefault = -1 );
virtual std::string ToString( NOTATION aNotation = NOTATION::SI ) const = 0;
std::string ToSpiceString() const { return ToString( NOTATION::SPICE ); }
}; };
template <typename T>
class SIM_VALUE_INST : public SIM_VALUE
{
public:
SIM_VALUE_INST() = default;
SIM_VALUE_INST( const T& aValue );
TYPE GetType() const override;
// TODO: Don't pass aNotation. Make a FromSpiceString() function instead.
// TODO: Don't use FromString(). Use assignment. Values should be immutable.
bool FromString( const std::string& aString, NOTATION aNotation = NOTATION::SI ) override;
std::string ToString( NOTATION aNotation = NOTATION::SI ) const override;
SIM_VALUE_INST& operator=( const SIM_VALUE& aOther ) override;
bool operator==( const T& aOther ) const;
bool operator==( const SIM_VALUE& aOther ) const override;
template <typename Type>
friend SIM_VALUE_INST<Type> operator+( const SIM_VALUE_INST<Type>& aLeft,
const SIM_VALUE_INST<Type>& aRight );
template <typename Type>
friend SIM_VALUE_INST<Type> operator-( const SIM_VALUE_INST<Type>& aLeft,
const SIM_VALUE_INST<Type>& aRight );
template <typename Type>
friend SIM_VALUE_INST<Type> operator*( const SIM_VALUE_INST<Type>& aLeft,
const SIM_VALUE_INST<Type>& aRight );
template <typename Type>
friend SIM_VALUE_INST<Type> operator/( const SIM_VALUE_INST<Type>& aLeft,
const SIM_VALUE_INST<Type>& aRight );
std::optional<T> Get() { return m_value; };
private:
std::string getMetricSuffix();
std::optional<T> m_value = std::nullopt;
};
typedef SIM_VALUE_INST<bool> SIM_VALUE_BOOL;
typedef SIM_VALUE_INST<int> SIM_VALUE_INT;
typedef SIM_VALUE_INST<double> SIM_VALUE_FLOAT;
typedef SIM_VALUE_INST<std::complex<double>> SIM_VALUE_COMPLEX;
typedef SIM_VALUE_INST<std::string> SIM_VALUE_STRING;
namespace SIM_VALUE_GRAMMAR namespace SIM_VALUE_GRAMMAR
{ {
template <NOTATION Notation> template <NOTATION Notation>

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -85,7 +85,7 @@ std::string SPICE_GENERATOR::ModelLine( const SPICE_ITEM& aItem ) const
name = param.info.name; name = param.info.name;
} }
value = param.value->ToSpiceString(); value = SIM_VALUE::ToSpice( param.value );
if( value == "" ) if( value == "" )
continue; continue;
@ -174,7 +174,7 @@ std::string SPICE_GENERATOR::ItemParams() const
{ {
std::string name = param.info.spiceInstanceName.empty() ? param.info.name std::string name = param.info.spiceInstanceName.empty() ? param.info.name
: param.info.spiceInstanceName; : param.info.spiceInstanceName;
std::string value = param.value->ToSpiceString(); std::string value = SIM_VALUE::ToSpice( param.value );
if( value != "" ) if( value != "" )
result.append( fmt::format( " {}={}", name, value ) ); result.append( fmt::format( " {}={}", name, value ) );
@ -184,8 +184,7 @@ std::string SPICE_GENERATOR::ItemParams() const
} }
std::string SPICE_GENERATOR::TunerCommand( const SPICE_ITEM& aItem, std::string SPICE_GENERATOR::TunerCommand( const SPICE_ITEM& aItem, double aValue ) const
const SIM_VALUE_FLOAT& aValue ) const
{ {
// No tuning available by default. // No tuning available by default.
return ""; return "";

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -58,7 +58,7 @@ public:
virtual std::string ItemModelName( const SPICE_ITEM& aItem ) const; virtual std::string ItemModelName( const SPICE_ITEM& aItem ) const;
virtual std::string ItemParams() const; virtual std::string ItemParams() const;
virtual std::string TunerCommand( const SPICE_ITEM& aItem, const SIM_VALUE_FLOAT& aValue ) const; virtual std::string TunerCommand( const SPICE_ITEM& aItem, double aValue ) const;
virtual std::vector<std::string> CurrentNames( const SPICE_ITEM& aItem ) const; virtual std::vector<std::string> CurrentNames( const SPICE_ITEM& aItem ) const;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -189,7 +189,7 @@ void SPICE_MODEL_PARSER::ReadModel( const SIM_LIBRARY_SPICE& aLibrary,
} }
for( int i = 0; i < static_cast<int>( sourceModel->GetParamCount() ); ++i ) for( int i = 0; i < static_cast<int>( sourceModel->GetParamCount() ); ++i )
m_model.SetParamValue( i, *sourceModel->GetParam( i ).value ); m_model.SetParamValue( i, sourceModel->GetParam( i ).value );
std::string paramName; std::string paramName;
@ -265,7 +265,7 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadTypeFromSpiceStrings( const std::string&
const std::string& aVersion, const std::string& aVersion,
bool aSkipDefaultLevel ) bool aSkipDefaultLevel )
{ {
std::unique_ptr<SIM_VALUE> readLevel = SIM_VALUE::Create( SIM_VALUE::TYPE_INT, aLevel ); std::string readLevel = wxString( aLevel ).BeforeFirst( '.' ).ToStdString();
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() ) for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{ {
@ -279,8 +279,7 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadTypeFromSpiceStrings( const std::string&
// Check if `aTypeString` starts with `typePrefix`. // Check if `aTypeString` starts with `typePrefix`.
if( boost::starts_with( boost::to_upper_copy( aTypeString ), typePrefix ) if( boost::starts_with( boost::to_upper_copy( aTypeString ), typePrefix )
&& ( level == readLevel->ToString() && ( level == readLevel || ( !aSkipDefaultLevel && isDefaultLevel && aLevel == "" ) )
|| ( !aSkipDefaultLevel && isDefaultLevel && aLevel == "" ) )
&& version == aVersion ) && version == aVersion )
{ {
return type; return type;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016 CERN * Copyright (C) 2016 CERN
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -81,7 +81,7 @@ TUNER_SLIDER::TUNER_SLIDER( SIM_PLOT_FRAME* aFrame, wxWindow* aParent,
// Special case for potentiometers because we don't have value ranges implemented yet. // Special case for potentiometers because we don't have value ranges implemented yet.
if( item->model->GetType() == SIM_MODEL::TYPE::R_POT ) if( item->model->GetType() == SIM_MODEL::TYPE::R_POT )
{ {
std::string valueStr = item->model->GetTunerParam()->value->ToSpiceString(); std::string valueStr = SIM_VALUE::ToSpice( item->model->GetTunerParam()->value );
if( valueStr != "" ) if( valueStr != "" )
m_value = SPICE_VALUE( valueStr ); m_value = SPICE_VALUE( valueStr );
@ -93,7 +93,7 @@ TUNER_SLIDER::TUNER_SLIDER( SIM_PLOT_FRAME* aFrame, wxWindow* aParent,
} }
else else
{ {
m_value = SPICE_VALUE( item->model->GetTunerParam()->value->ToSpiceString() ); m_value = SPICE_VALUE( SIM_VALUE::ToSpice( item->model->GetTunerParam()->value ) );
m_min = SPICE_VALUE( 0.5 ) * m_value; m_min = SPICE_VALUE( 0.5 ) * m_value;
m_max = SPICE_VALUE( 2.0 ) * m_value; m_max = SPICE_VALUE( 2.0 ) * m_value;
} }

View File

@ -58,12 +58,12 @@ public:
fmt::format( "{}{}_Usual", fmt::format( "{}{}_Usual",
boost::to_upper_copy( aModel.GetSpiceInfo().modelType ), boost::to_upper_copy( aModel.GetSpiceInfo().modelType ),
aModelIndex ) ); aModelIndex ) );
BOOST_CHECK_EQUAL( aModel.FindParam( "bv" )->value->ToString(), "1.1u" ); BOOST_CHECK_EQUAL( aModel.FindParam( "bv" )->value, "1.1u" );
BOOST_CHECK_EQUAL( aModel.FindParam( "cjo" )->value->ToString(), "2.2m" ); BOOST_CHECK_EQUAL( aModel.FindParam( "cjo" )->value, "2.2m" );
BOOST_CHECK_EQUAL( aModel.FindParam( "ibv" )->value->ToString(), "3.3" ); BOOST_CHECK_EQUAL( aModel.FindParam( "ibv" )->value, "3.3" );
BOOST_CHECK_EQUAL( aModel.FindParam( "is" )->value->ToString(), "4.4k" ); BOOST_CHECK_EQUAL( aModel.FindParam( "is" )->value, "4.4k" );
BOOST_CHECK_EQUAL( aModel.FindParam( "m_" )->value->ToString(), "5.5M" ); BOOST_CHECK_EQUAL( aModel.FindParam( "m_" )->value, "5.5M" );
BOOST_CHECK_EQUAL( aModel.FindParam( "n" )->value->ToString(), "6.6G" ); BOOST_CHECK_EQUAL( aModel.FindParam( "n" )->value, "6.6G" );
} }
void CompareToEmptyModel( const SIM_MODEL& aModel, const std::string& aModelName, int aModelIndex ) void CompareToEmptyModel( const SIM_MODEL& aModel, const std::string& aModelName, int aModelIndex )
@ -79,7 +79,7 @@ public:
{ {
BOOST_TEST_CONTEXT( "Param name: " << aModel.GetParam( i ).info.name ) BOOST_TEST_CONTEXT( "Param name: " << aModel.GetParam( i ).info.name )
{ {
BOOST_CHECK_EQUAL( aModel.GetParamOverride( i ).value->ToString(), "" ); BOOST_CHECK_EQUAL( aModel.GetParamOverride( i ).value, "" );
} }
} }
} }
@ -125,16 +125,19 @@ public:
BOOST_TEST_CONTEXT( "Param name: " << paramName ) BOOST_TEST_CONTEXT( "Param name: " << paramName )
{ {
if( i % 10 == 0 ) if( i % 10 == 0 )
BOOST_CHECK_EQUAL( aModel.FindParam( paramName )->value->ToString(), "0" ); {
BOOST_CHECK( aModel.FindParam( paramName )->value == "0M"
|| aModel.FindParam( paramName )->value == "0" );
}
else if( aModel.FindParam( paramName )->info.type == SIM_VALUE::TYPE_INT ) else if( aModel.FindParam( paramName )->info.type == SIM_VALUE::TYPE_INT )
{ {
BOOST_CHECK_EQUAL( aModel.FindParam( paramName )->value->ToString(), BOOST_CHECK_EQUAL( aModel.FindParam( paramName )->value,
fmt::format( "{:d}", i % 10 ) ); fmt::format( "{:d}", i % 10 ) );
} }
else else
{ {
BOOST_CHECK_EQUAL( aModel.FindParam( paramName )->value->ToString(), BOOST_CHECK_EQUAL( aModel.FindParam( paramName )->value,
fmt::format( "{}.0000{}G", i % 10, i % 10 ) ); fmt::format( "{}000.0{}M", i % 10, i % 10 ) );
} }
} }
} }
@ -253,35 +256,35 @@ BOOST_AUTO_TEST_CASE( Diodes )
case 0: case 0:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "1N4148" ); BOOST_CHECK_EQUAL( modelName, "1N4148" );
BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value->ToString(), "100" ); BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value, "100" );
BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value->ToString(), "4p" ); BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value, "4p" );
BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value->ToString(), "100u" ); BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value, "100u" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "4n" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "4n" );
BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value->ToString(), "330m" ); BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value, "0.33" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "2" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "2" );
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "500m" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "0.5" );
BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value->ToString(), "10n" ); BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value, "10n" );
BOOST_CHECK_EQUAL( model.FindParam( "vj" )->value->ToString(), "800m" ); BOOST_CHECK_EQUAL( model.FindParam( "vj" )->value, "0.8" );
break; break;
case 1: case 1:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D1" ); BOOST_CHECK_EQUAL( modelName, "D1" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "1.23n" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "1.23n" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "1.23" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "1.23" );
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "789m" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "0.789" );
BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value->ToString(), "12.34m" ); BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value, "12.34m" );
BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value->ToString(), "3" ); BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value, "3" );
BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value->ToString(), "1.23" ); BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value, "1.23" );
BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value->ToString(), "900f" ); BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value, "0.9p" );
BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value->ToString(), "560m" ); BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value, "0.56" );
BOOST_CHECK_EQUAL( model.FindParam( "vj" )->value->ToString(), "780m" ); BOOST_CHECK_EQUAL( model.FindParam( "vj" )->value, "0.78" );
BOOST_CHECK_EQUAL( model.FindParam( "fc" )->value->ToString(), "900m" ); BOOST_CHECK_EQUAL( model.FindParam( "fc" )->value, "0.9" );
BOOST_CHECK_EQUAL( model.FindParam( "isr" )->value->ToString(), "12.34n" ); BOOST_CHECK_EQUAL( model.FindParam( "isr" )->value, "12.34n" );
BOOST_CHECK_EQUAL( model.FindParam( "nr" )->value->ToString(), "2.345" ); BOOST_CHECK_EQUAL( model.FindParam( "nr" )->value, "2.345" );
BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value->ToString(), "100" ); BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value, "100" );
BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value->ToString(), "100u" ); BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value, "100u" );
BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value->ToString(), "12.34n" ); BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value, "12.34n" );
break; break;
case 2: case 2:
@ -292,12 +295,12 @@ BOOST_AUTO_TEST_CASE( Diodes )
case 4: case 4:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D4" ); BOOST_CHECK_EQUAL( modelName, "D4" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "100f" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "0.1p" );
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "2" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "2" );
BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value->ToString(), "3p" ); BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value, "3p" );
BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value->ToString(), "45n" ); BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value, "45n" );
BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value->ToString(), "678" ); BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value, "678" );
BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value->ToString(), "100f" ); BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value, "0.1p" );
break; break;
case 5: case 5:
@ -322,12 +325,12 @@ BOOST_AUTO_TEST_CASE( Diodes )
case 18: case 18:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D<>/?:\\|[]!@#$%^&-_18" ); BOOST_CHECK_EQUAL( modelName, "D<>/?:\\|[]!@#$%^&-_18" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "-1.1" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "-1.1" );
BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value->ToString(), "2.2" ); BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value, "2.2" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "-3.3m" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "-3.3m" );
BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value->ToString(), "44k" ); BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value, "44k" );
BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value->ToString(), "55u" ); BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value, "55u" );
BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value->ToString(), "6.6M" ); BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value, "6.6M" );
break; break;
case 19: case 19:
@ -339,115 +342,115 @@ BOOST_AUTO_TEST_CASE( Diodes )
case 22: case 22:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D22" ); BOOST_CHECK_EQUAL( modelName, "D22" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "11.1n" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "11.1n" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "2.2" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "2.2" );
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "33.3m" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "33.3m" );
BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value->ToString(), "99.9" ); BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value, "99.9" );
BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value->ToString(), "3" ); BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value, "3" );
BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value->ToString(), "1.1" ); BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value, "1.1" );
break; break;
case 23: case 23:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D23" ); BOOST_CHECK_EQUAL( modelName, "D23" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "11.1n" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "11.1n" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "2.2" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "2.2" );
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "33.3m" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "33.3m" );
BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value->ToString(), "111.1" ); BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value, "111.1" );
BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value->ToString(), "3" ); BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value, "3" );
BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value->ToString(), "2.2" ); BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value, "2.2" );
BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value->ToString(), "300m" ); BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value, "0.3" );
break; break;
case 24: case 24:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D24" ); BOOST_CHECK_EQUAL( modelName, "D24" );
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "11.1n" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "11.1n" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "1.1" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "1.1" );
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "33.3m" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "33.3m" );
BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value->ToString(), "99.9" ); BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value, "99.9" );
BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value->ToString(), "3" ); BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value, "3" );
BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value->ToString(), "1.1" ); BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value, "1.1" );
break; break;
case 25: case 25:
BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D ); BOOST_CHECK( model.GetType() == SIM_MODEL::TYPE::D );
BOOST_CHECK_EQUAL( modelName, "D25" ); BOOST_CHECK_EQUAL( modelName, "D25" );
//level //level
BOOST_CHECK_EQUAL( model.FindParam( "is" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "is" )->value, "0M" );
//js //js
BOOST_CHECK_EQUAL( model.FindParam( "jsw" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "jsw" )->value, "1000.01M" );
BOOST_CHECK_EQUAL( model.FindParam( "tnom" )->value->ToString(), "2.00002G" ); BOOST_CHECK_EQUAL( model.FindParam( "tnom" )->value, "2000.02M" );
//tref //tref
BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value->ToString(), "3.00003G" ); BOOST_CHECK_EQUAL( model.FindParam( "rs" )->value, "3000.03M" );
BOOST_CHECK_EQUAL( model.FindParam( "trs" )->value->ToString(), "4.00004G" ); BOOST_CHECK_EQUAL( model.FindParam( "trs" )->value, "4000.04M" );
//trs1 //trs1
BOOST_CHECK_EQUAL( model.FindParam( "trs2" )->value->ToString(), "5.00005G" ); BOOST_CHECK_EQUAL( model.FindParam( "trs2" )->value, "5000.05M" );
BOOST_CHECK_EQUAL( model.FindParam( "n" )->value->ToString(), "6.00006G" ); BOOST_CHECK_EQUAL( model.FindParam( "n" )->value, "6000.06M" );
BOOST_CHECK_EQUAL( model.FindParam( "ns" )->value->ToString(), "7.00007G" ); BOOST_CHECK_EQUAL( model.FindParam( "ns" )->value, "7000.07M" );
BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value->ToString(), "8.00008G" ); BOOST_CHECK_EQUAL( model.FindParam( "tt" )->value, "8000.08M" );
BOOST_CHECK_EQUAL( model.FindParam( "ttt1" )->value->ToString(), "9.00009G" ); BOOST_CHECK_EQUAL( model.FindParam( "ttt1" )->value, "9000.09M" );
BOOST_CHECK_EQUAL( model.FindParam( "ttt2" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "ttt2" )->value, "0M" );
BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "cjo" )->value, "1000.01M" );
//cj0 //cj0
//cj //cj
BOOST_CHECK_EQUAL( model.FindParam( "vj" )->value->ToString(), "2.00002G" ); BOOST_CHECK_EQUAL( model.FindParam( "vj" )->value, "2000.02M" );
//pb //pb
BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value->ToString(), "3.00003G" ); BOOST_CHECK_EQUAL( model.FindParam( "m_" )->value, "3000.03M" );
//mj //mj
BOOST_CHECK_EQUAL( model.FindParam( "tm1" )->value->ToString(), "4.00004G" ); BOOST_CHECK_EQUAL( model.FindParam( "tm1" )->value, "4000.04M" );
BOOST_CHECK_EQUAL( model.FindParam( "tm2" )->value->ToString(), "5.00005G" ); BOOST_CHECK_EQUAL( model.FindParam( "tm2" )->value, "5000.05M" );
BOOST_CHECK_EQUAL( model.FindParam( "cjp" )->value->ToString(), "6.00006G" ); BOOST_CHECK_EQUAL( model.FindParam( "cjp" )->value, "6000.06M" );
//cjsw //cjsw
BOOST_CHECK_EQUAL( model.FindParam( "php" )->value->ToString(), "7.00007G" ); BOOST_CHECK_EQUAL( model.FindParam( "php" )->value, "7000.07M" );
BOOST_CHECK_EQUAL( model.FindParam( "mjsw" )->value->ToString(), "8.00008G" ); BOOST_CHECK_EQUAL( model.FindParam( "mjsw" )->value, "8000.08M" );
BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value->ToString(), "9.00009G" ); BOOST_CHECK_EQUAL( model.FindParam( "ikf" )->value, "9000.09M" );
//ik //ik
BOOST_CHECK_EQUAL( model.FindParam( "ikr" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "ikr" )->value, "0M" );
BOOST_CHECK_EQUAL( model.FindParam( "nbv" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "nbv" )->value, "1000.01M" );
BOOST_CHECK_EQUAL( model.FindParam( "area_" )->value->ToString(), "2.00002G" ); BOOST_CHECK_EQUAL( model.FindParam( "area_" )->value, "2000.02M" );
BOOST_CHECK_EQUAL( model.FindParam( "pj_" )->value->ToString(), "3.00003G" ); BOOST_CHECK_EQUAL( model.FindParam( "pj_" )->value, "3000.03M" );
BOOST_CHECK_EQUAL( model.FindParam( "tlev" )->value->ToString(), "4" ); //"4.00004G" ); BOOST_CHECK_EQUAL( model.FindParam( "tlev" )->value, "4" );
BOOST_CHECK_EQUAL( model.FindParam( "tlevc" )->value->ToString(), "5" ); //"5.00005G" ); BOOST_CHECK_EQUAL( model.FindParam( "tlevc" )->value, "5" );
BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value->ToString(), "6.00006G" ); BOOST_CHECK_EQUAL( model.FindParam( "eg" )->value, "6000.06M" );
BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value->ToString(), "7.00007G" ); BOOST_CHECK_EQUAL( model.FindParam( "xti" )->value, "7000.07M" );
BOOST_CHECK_EQUAL( model.FindParam( "cta" )->value->ToString(), "8.00008G" ); BOOST_CHECK_EQUAL( model.FindParam( "cta" )->value, "8000.08M" );
//ctc //ctc
BOOST_CHECK_EQUAL( model.FindParam( "ctp" )->value->ToString(), "9.00009G" ); BOOST_CHECK_EQUAL( model.FindParam( "ctp" )->value, "9000.09M" );
BOOST_CHECK_EQUAL( model.FindParam( "tpb" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "tpb" )->value, "0M" );
//tvj //tvj
BOOST_CHECK_EQUAL( model.FindParam( "tphp" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "tphp" )->value, "1000.01M" );
BOOST_CHECK_EQUAL( model.FindParam( "jtun" )->value->ToString(), "2.00002G" ); BOOST_CHECK_EQUAL( model.FindParam( "jtun" )->value, "2000.02M" );
BOOST_CHECK_EQUAL( model.FindParam( "jtunsw" )->value->ToString(), "3.00003G" ); BOOST_CHECK_EQUAL( model.FindParam( "jtunsw" )->value, "3000.03M" );
BOOST_CHECK_EQUAL( model.FindParam( "ntun" )->value->ToString(), "4.00004G" ); BOOST_CHECK_EQUAL( model.FindParam( "ntun" )->value, "4000.04M" );
BOOST_CHECK_EQUAL( model.FindParam( "xtitun" )->value->ToString(), "5.00005G" ); BOOST_CHECK_EQUAL( model.FindParam( "xtitun" )->value, "5000.05M" );
BOOST_CHECK_EQUAL( model.FindParam( "keg" )->value->ToString(), "6.00006G" ); BOOST_CHECK_EQUAL( model.FindParam( "keg" )->value, "6000.06M" );
BOOST_CHECK_EQUAL( model.FindParam( "kf" )->value->ToString(), "7.00007G" ); BOOST_CHECK_EQUAL( model.FindParam( "kf" )->value, "7000.07M" );
BOOST_CHECK_EQUAL( model.FindParam( "af" )->value->ToString(), "8.00008G" ); BOOST_CHECK_EQUAL( model.FindParam( "af" )->value, "8000.08M" );
BOOST_CHECK_EQUAL( model.FindParam( "fc" )->value->ToString(), "9.00009G" ); BOOST_CHECK_EQUAL( model.FindParam( "fc" )->value, "9000.09M" );
BOOST_CHECK_EQUAL( model.FindParam( "fcs" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "fcs" )->value, "0M" );
BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "bv" )->value, "1000.01M" );
BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value->ToString(), "2.00002G" ); BOOST_CHECK_EQUAL( model.FindParam( "ibv" )->value, "2000.02M" );
//ib //ib
BOOST_CHECK_EQUAL( model.FindParam( "tcv" )->value->ToString(), "3.00003G" ); BOOST_CHECK_EQUAL( model.FindParam( "tcv" )->value, "3000.03M" );
BOOST_CHECK_EQUAL( model.FindParam( "cond" )->value->ToString(), "4.00004G" ); BOOST_CHECK_EQUAL( model.FindParam( "cond" )->value, "4000.04M" );
BOOST_CHECK_EQUAL( model.FindParam( "isr" )->value->ToString(), "5.00005G" ); BOOST_CHECK_EQUAL( model.FindParam( "isr" )->value, "5000.05M" );
BOOST_CHECK_EQUAL( model.FindParam( "nr" )->value->ToString(), "6.00006G" ); BOOST_CHECK_EQUAL( model.FindParam( "nr" )->value, "6000.06M" );
BOOST_CHECK_EQUAL( model.FindParam( "fv_max" )->value->ToString(), "7.00007G" ); BOOST_CHECK_EQUAL( model.FindParam( "fv_max" )->value, "7000.07M" );
BOOST_CHECK_EQUAL( model.FindParam( "bv_max" )->value->ToString(), "8.00008G" ); BOOST_CHECK_EQUAL( model.FindParam( "bv_max" )->value, "8000.08M" );
BOOST_CHECK_EQUAL( model.FindParam( "id_max" )->value->ToString(), "9.00009G" ); BOOST_CHECK_EQUAL( model.FindParam( "id_max" )->value, "9000.09M" );
BOOST_CHECK_EQUAL( model.FindParam( "te_max" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "te_max" )->value, "0M" );
BOOST_CHECK_EQUAL( model.FindParam( "pd_max" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "pd_max" )->value, "1000.01M" );
BOOST_CHECK_EQUAL( model.FindParam( "rth0" )->value->ToString(), "2.00002G" ); BOOST_CHECK_EQUAL( model.FindParam( "rth0" )->value, "2000.02M" );
BOOST_CHECK_EQUAL( model.FindParam( "cth0" )->value->ToString(), "3.00003G" ); BOOST_CHECK_EQUAL( model.FindParam( "cth0" )->value, "3000.03M" );
BOOST_CHECK_EQUAL( model.FindParam( "lm_" )->value->ToString(), "4.00004G" ); BOOST_CHECK_EQUAL( model.FindParam( "lm_" )->value, "4000.04M" );
BOOST_CHECK_EQUAL( model.FindParam( "lp_" )->value->ToString(), "5.00005G" ); BOOST_CHECK_EQUAL( model.FindParam( "lp_" )->value, "5000.05M" );
BOOST_CHECK_EQUAL( model.FindParam( "wm_" )->value->ToString(), "6.00006G" ); BOOST_CHECK_EQUAL( model.FindParam( "wm_" )->value, "6000.06M" );
BOOST_CHECK_EQUAL( model.FindParam( "wp_" )->value->ToString(), "7.00007G" ); BOOST_CHECK_EQUAL( model.FindParam( "wp_" )->value, "7000.07M" );
BOOST_CHECK_EQUAL( model.FindParam( "xom" )->value->ToString(), "8.00008G" ); BOOST_CHECK_EQUAL( model.FindParam( "xom" )->value, "8000.08M" );
BOOST_CHECK_EQUAL( model.FindParam( "xoi" )->value->ToString(), "9.00009G" ); BOOST_CHECK_EQUAL( model.FindParam( "xoi" )->value, "9000.09M" );
BOOST_CHECK_EQUAL( model.FindParam( "xm" )->value->ToString(), "0" ); BOOST_CHECK_EQUAL( model.FindParam( "xm" )->value, "0M" );
BOOST_CHECK_EQUAL( model.FindParam( "xp" )->value->ToString(), "1.00001G" ); BOOST_CHECK_EQUAL( model.FindParam( "xp" )->value, "1000.01M" );
//d //d
break; break;