Move (de)serialization of models into fields to new SIM_SERDE class
This commit is contained in:
parent
f846bc833b
commit
490069c5e6
|
@ -285,6 +285,7 @@ set( EESCHEMA_SRCS
|
||||||
sim/sim_library_spice.cpp
|
sim/sim_library_spice.cpp
|
||||||
sim/sim_library_kibis.cpp
|
sim/sim_library_kibis.cpp
|
||||||
sim/sim_lib_mgr.cpp
|
sim/sim_lib_mgr.cpp
|
||||||
|
sim/sim_serde.cpp
|
||||||
sim/sim_model.cpp
|
sim/sim_model.cpp
|
||||||
sim/sim_model_behavioral.cpp
|
sim/sim_model_behavioral.cpp
|
||||||
sim/sim_model_ideal.cpp
|
sim/sim_model_ideal.cpp
|
||||||
|
|
|
@ -54,27 +54,6 @@ using DEVICE_TYPE = SIM_MODEL::DEVICE_TYPE_;
|
||||||
using TYPE = SIM_MODEL::TYPE;
|
using TYPE = SIM_MODEL::TYPE;
|
||||||
|
|
||||||
|
|
||||||
namespace SIM_MODEL_PARSER
|
|
||||||
{
|
|
||||||
using namespace SIM_MODEL_GRAMMAR;
|
|
||||||
|
|
||||||
template <typename Rule> struct fieldParamValuePairsSelector : std::false_type {};
|
|
||||||
template <> struct fieldParamValuePairsSelector<param> : std::true_type {};
|
|
||||||
template <> struct fieldParamValuePairsSelector<quotedStringContent> : std::true_type {};
|
|
||||||
template <> struct fieldParamValuePairsSelector<unquotedString> : std::true_type {};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Rule> struct pinSequenceSelector : std::false_type {};
|
|
||||||
template <> struct pinSequenceSelector<pinNumber> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename Rule> struct fieldInferValueSelector : std::false_type {};
|
|
||||||
template <> struct fieldInferValueSelector<fieldInferValueType> : std::true_type {};
|
|
||||||
template <> struct fieldInferValueSelector<fieldInferValuePrimaryValue> : std::true_type {};
|
|
||||||
template <> struct fieldInferValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> : std::true_type {};
|
|
||||||
template <> struct fieldInferValueSelector<fieldParamValuePairs> : std::true_type {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL::DEVICE_INFO SIM_MODEL::DeviceTypeInfo( DEVICE_TYPE_ aDeviceType )
|
SIM_MODEL::DEVICE_INFO SIM_MODEL::DeviceTypeInfo( DEVICE_TYPE_ aDeviceType )
|
||||||
{
|
{
|
||||||
switch( aDeviceType )
|
switch( aDeviceType )
|
||||||
|
@ -425,9 +404,9 @@ TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields, int aSymbolPi
|
||||||
|
|
||||||
// Still no type information.
|
// Still no type information.
|
||||||
// We try to infer the model from the mandatory fields in this case.
|
// We try to infer the model from the mandatory fields in this case.
|
||||||
return InferTypeFromRefAndValue( GetFieldValue( &aFields, REFERENCE_FIELD ),
|
return SIM_SERDE::InferTypeFromRefAndValue( GetFieldValue( &aFields, REFERENCE_FIELD ),
|
||||||
GetFieldValue( &aFields, VALUE_FIELD ),
|
GetFieldValue( &aFields, VALUE_FIELD ),
|
||||||
aSymbolPinCount );
|
aSymbolPinCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -451,45 +430,6 @@ DEVICE_TYPE SIM_MODEL::InferDeviceTypeFromRef( const std::string& aRef )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TYPE SIM_MODEL::InferTypeFromRefAndValue( const std::string& aRef, const std::string& aValue,
|
|
||||||
int aSymbolPinCount )
|
|
||||||
{
|
|
||||||
std::string typeString;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tao::pegtl::string_input<> in( aValue, VALUE_FIELD );
|
|
||||||
auto root = tao::pegtl::parse_tree::parse<SIM_MODEL_PARSER::fieldInferValueGrammar,
|
|
||||||
SIM_MODEL_PARSER::fieldInferValueSelector,
|
|
||||||
tao::pegtl::nothing,
|
|
||||||
SIM_MODEL_PARSER::control>( in );
|
|
||||||
|
|
||||||
for( const auto& node : root->children )
|
|
||||||
{
|
|
||||||
if( node->is_type<SIM_MODEL_PARSER::fieldInferValueType>() )
|
|
||||||
typeString = node->string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( const tao::pegtl::parse_error& )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DEVICE_TYPE deviceType = InferDeviceTypeFromRef( aRef );
|
|
||||||
|
|
||||||
// Exception. Potentiometer model is determined from pin count.
|
|
||||||
if( deviceType == DEVICE_TYPE_::R && aSymbolPinCount == 3 )
|
|
||||||
return TYPE::R_POT;
|
|
||||||
|
|
||||||
for( TYPE type : TYPE_ITERATOR() )
|
|
||||||
{
|
|
||||||
if( TypeInfo( type ).deviceType == deviceType && TypeInfo( type ).fieldValue == typeString )
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TYPE::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
TYPE SIM_MODEL::InferTypeFromLegacyFields( const std::vector<T>& aFields )
|
TYPE SIM_MODEL::InferTypeFromLegacyFields( const std::vector<T>& aFields )
|
||||||
{
|
{
|
||||||
|
@ -967,17 +907,30 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType )
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL::SIM_MODEL( TYPE aType ) :
|
SIM_MODEL::SIM_MODEL( TYPE aType ) :
|
||||||
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) )
|
SIM_MODEL( aType,
|
||||||
|
std::make_unique<SPICE_GENERATOR>( *this ),
|
||||||
|
std::make_unique<SIM_SERDE>( *this ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SIM_MODEL::SIM_MODEL( TYPE aType,
|
||||||
|
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
|
||||||
|
SIM_MODEL( aType,
|
||||||
|
std::move( aSpiceGenerator ),
|
||||||
|
std::make_unique<SIM_SERDE>( *this ) )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
|
SIM_MODEL::SIM_MODEL( TYPE aType,
|
||||||
m_baseModel( nullptr ),
|
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
|
||||||
m_spiceGenerator( std::move( aSpiceGenerator ) ),
|
std::unique_ptr<SIM_SERDE> aSerde ) :
|
||||||
m_type( aType ),
|
m_baseModel( nullptr ),
|
||||||
m_isEnabled( true ),
|
m_serde( std::move( aSerde ) ),
|
||||||
m_isInferred( false )
|
m_spiceGenerator( std::move( aSpiceGenerator ) ),
|
||||||
|
m_type( aType ),
|
||||||
|
m_isEnabled( true ),
|
||||||
|
m_isInferred( false )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,127 +990,21 @@ void SIM_MODEL::WriteInferredDataFields( std::vector<T>& aFields, const std::str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string SIM_MODEL::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
if( aIsFirst )
|
|
||||||
aIsFirst = false;
|
|
||||||
else
|
|
||||||
result.append( " " );
|
|
||||||
|
|
||||||
std::string name = aParam.info.name;
|
|
||||||
|
|
||||||
// Because of collisions with instance parameters, we append some model parameters with "_".
|
|
||||||
if( boost::ends_with( aParam.info.name, "_" ) )
|
|
||||||
name = aParam.info.name.substr( 0, aParam.info.name.length() - 1);
|
|
||||||
|
|
||||||
std::string value = aParam.value->ToString();
|
|
||||||
if( value.find( " " ) != std::string::npos )
|
|
||||||
value = "\"" + value + "\"";
|
|
||||||
|
|
||||||
result.append( fmt::format( "{}={}", aParam.info.name, value ) );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string SIM_MODEL::GenerateValueField( const std::string& aPairSeparator ) const
|
std::string SIM_MODEL::GenerateValueField( const std::string& aPairSeparator ) const
|
||||||
{
|
{
|
||||||
std::string result;
|
return m_serde->GenerateValue();
|
||||||
bool isFirst = true;
|
|
||||||
|
|
||||||
for( int i = 0; i < GetParamCount(); ++i )
|
|
||||||
{
|
|
||||||
const PARAM& param = GetParam( i );
|
|
||||||
|
|
||||||
if( i == 0 && hasPrimaryValue() )
|
|
||||||
{
|
|
||||||
result.append( param.value->ToString() );
|
|
||||||
isFirst = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( param.value->ToString() == "" )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
result.append( GenerateParamValuePair( param, isFirst ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result == "" )
|
|
||||||
result = GetDeviceTypeInfo().fieldValue;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string SIM_MODEL::GenerateParamsField( const std::string& aPairSeparator ) const
|
std::string SIM_MODEL::GenerateParamsField( const std::string& aPairSeparator ) const
|
||||||
{
|
{
|
||||||
std::string result;
|
return m_serde->GenerateParams();
|
||||||
bool isFirst = true;
|
|
||||||
|
|
||||||
for( const PARAM& param : m_params )
|
|
||||||
{
|
|
||||||
if( param.value->ToString() == "" )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
result.append( GenerateParamValuePair( param, isFirst ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL::ParseParamsField( const std::string& aParamsField )
|
void SIM_MODEL::ParseParamsField( const std::string& aParamsField )
|
||||||
{
|
{
|
||||||
tao::pegtl::string_input<> in( aParamsField, "Sim_Params" );
|
m_serde->ParseParams( aParamsField );
|
||||||
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Using parse tree instead of actions because we don't care about performance that much,
|
|
||||||
// and having a tree greatly simplifies things.
|
|
||||||
root = tao::pegtl::parse_tree::parse<
|
|
||||||
SIM_MODEL_PARSER::fieldParamValuePairsGrammar,
|
|
||||||
SIM_MODEL_PARSER::fieldParamValuePairsSelector,
|
|
||||||
tao::pegtl::nothing,
|
|
||||||
SIM_MODEL_PARSER::control>
|
|
||||||
( in );
|
|
||||||
}
|
|
||||||
catch( const tao::pegtl::parse_error& e )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( e.what() );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string paramName;
|
|
||||||
|
|
||||||
for( const auto& node : root->children )
|
|
||||||
{
|
|
||||||
if( node->is_type<SIM_MODEL_PARSER::param>() )
|
|
||||||
paramName = node->string();
|
|
||||||
// TODO: Do something with number<SIM_VALUE::TYPE_INT, ...>.
|
|
||||||
// It doesn't seem too useful?
|
|
||||||
else if( node->is_type<SIM_MODEL_PARSER::quotedStringContent>()
|
|
||||||
|| node->is_type<SIM_MODEL_PARSER::unquotedString>() )
|
|
||||||
{
|
|
||||||
wxASSERT( paramName != "" );
|
|
||||||
// TODO: Shouldn't be named "...fromSpiceCode" here...
|
|
||||||
|
|
||||||
SetParamValue( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI );
|
|
||||||
}
|
|
||||||
else if( node->is_type<SIM_MODEL_PARSER::quotedString>() )
|
|
||||||
{
|
|
||||||
std::string str = node->string();
|
|
||||||
|
|
||||||
// Unescape quotes.
|
|
||||||
boost::replace_all( str, "\\\"", "\"" );
|
|
||||||
|
|
||||||
SetParamValue( paramName, str, SIM_VALUE_GRAMMAR::NOTATION::SI );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxFAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1165,51 +1012,13 @@ void SIM_MODEL::ParsePinsField( unsigned aSymbolPinCount, const std::string& aPi
|
||||||
{
|
{
|
||||||
CreatePins( aSymbolPinCount );
|
CreatePins( aSymbolPinCount );
|
||||||
|
|
||||||
if( aPinsField == "" )
|
m_serde->ParsePins( aPinsField );
|
||||||
return;
|
|
||||||
|
|
||||||
tao::pegtl::string_input<> in( aPinsField, PINS_FIELD );
|
|
||||||
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
root = tao::pegtl::parse_tree::parse<SIM_MODEL_PARSER::pinSequenceGrammar,
|
|
||||||
SIM_MODEL_PARSER::pinSequenceSelector,
|
|
||||||
tao::pegtl::nothing,
|
|
||||||
SIM_MODEL_PARSER::control>( in );
|
|
||||||
}
|
|
||||||
catch( const tao::pegtl::parse_error& e )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( e.what() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( static_cast<int>( root->children.size() ) != GetPinCount() )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( wxString::Format( _( "%s describes %lu pins, expected %u" ),
|
|
||||||
PINS_FIELD,
|
|
||||||
root->children.size(),
|
|
||||||
GetPinCount() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( int pinIndex = 0; pinIndex < static_cast<int>( root->children.size() ); ++pinIndex )
|
|
||||||
{
|
|
||||||
if( root->children.at( pinIndex )->string() == "~" )
|
|
||||||
SetPinSymbolPinNumber( pinIndex, "" );
|
|
||||||
else
|
|
||||||
SetPinSymbolPinNumber( pinIndex, root->children.at( pinIndex )->string() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SIM_MODEL::ParseEnableField( const std::string& aEnableField )
|
void SIM_MODEL::ParseEnableField( const std::string& aEnableField )
|
||||||
{
|
{
|
||||||
if( aEnableField == "" )
|
m_serde->ParseEnable( aEnableField );
|
||||||
return;
|
|
||||||
|
|
||||||
char c = boost::to_lower_copy( aEnableField )[0];
|
|
||||||
|
|
||||||
if( c == 'n' || c == 'f' || c == '0' )
|
|
||||||
m_isEnabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1234,54 +1043,15 @@ void SIM_MODEL::InferredReadDataFields( unsigned aSymbolPinCount, const std::vec
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: Don't call this multiple times.
|
// TODO: Don't call this multiple times.
|
||||||
if( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
if( SIM_SERDE::InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||||
GetFieldValue( aFields, VALUE_FIELD ),
|
GetFieldValue( aFields, VALUE_FIELD ),
|
||||||
aSymbolPinCount ) != GetType() )
|
aSymbolPinCount ) != GetType() )
|
||||||
{
|
{
|
||||||
// Not an inferred model. Nothing to do here.
|
// Not an inferred model. Nothing to do here.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
m_serde->ParseValue( GetFieldValue( aFields, VALUE_FIELD ) );
|
||||||
{
|
|
||||||
// TODO: Don't call this multiple times.
|
|
||||||
tao::pegtl::string_input<> in( GetFieldValue( aFields, VALUE_FIELD ), VALUE_FIELD );
|
|
||||||
auto root = tao::pegtl::parse_tree::parse<SIM_MODEL_PARSER::fieldInferValueGrammar,
|
|
||||||
SIM_MODEL_PARSER::fieldInferValueSelector,
|
|
||||||
tao::pegtl::nothing,
|
|
||||||
SIM_MODEL_PARSER::control>( in );
|
|
||||||
|
|
||||||
for( const auto& node : root->children )
|
|
||||||
{
|
|
||||||
if( node->is_type<SIM_MODEL_PARSER::fieldInferValuePrimaryValue>() )
|
|
||||||
{
|
|
||||||
if( hasPrimaryValue() )
|
|
||||||
{
|
|
||||||
for( const auto& subnode : node->children )
|
|
||||||
{
|
|
||||||
if( subnode->is_type<SIM_MODEL_PARSER::number<SIM_VALUE::TYPE_FLOAT,
|
|
||||||
SIM_VALUE::NOTATION::SI>>() )
|
|
||||||
{
|
|
||||||
SetParamValue( 0, subnode->string() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR(
|
|
||||||
wxString::Format( _( "Simulation model of type '%s' cannot have a primary value (which is '%s') in Value field" ),
|
|
||||||
GetTypeInfo().fieldValue,
|
|
||||||
node->string() ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( node->is_type<SIM_MODEL_PARSER::fieldParamValuePairs>() )
|
|
||||||
ParseParamsField( node->string() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( const tao::pegtl::parse_error& e )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( e.what() );
|
|
||||||
}
|
|
||||||
|
|
||||||
SetIsInferred( true );
|
SetIsInferred( true );
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,102 +39,7 @@
|
||||||
|
|
||||||
class SIM_LIBRARY;
|
class SIM_LIBRARY;
|
||||||
class SPICE_GENERATOR;
|
class SPICE_GENERATOR;
|
||||||
|
class SIM_SERDE;
|
||||||
|
|
||||||
namespace SIM_MODEL_GRAMMAR
|
|
||||||
{
|
|
||||||
using namespace SIM_VALUE_GRAMMAR;
|
|
||||||
|
|
||||||
struct sep : plus<space> {};
|
|
||||||
|
|
||||||
|
|
||||||
struct legacyPinNumber : digits {};
|
|
||||||
struct legacyPinSequence : list<legacyPinNumber, sep> {};
|
|
||||||
|
|
||||||
struct legacyPinSequenceGrammar : must<legacyPinSequence,
|
|
||||||
tao::pegtl::eof> {};
|
|
||||||
|
|
||||||
|
|
||||||
struct pinNumber : plus<not_at<sep>, any> {};
|
|
||||||
struct pinSequence : list<pinNumber, sep> {};
|
|
||||||
struct pinSequenceGrammar : must<opt<sep>,
|
|
||||||
opt<pinSequence>,
|
|
||||||
opt<sep>,
|
|
||||||
tao::pegtl::eof> {};
|
|
||||||
|
|
||||||
struct param : plus<alnum> {};
|
|
||||||
|
|
||||||
struct unquotedString : plus<not_at<sep>, any> {};
|
|
||||||
struct quotedStringContent : star<not_at<one<'"'>>, any> {}; // TODO: Allow escaping '"'.
|
|
||||||
struct quotedString : seq<one<'"'>,
|
|
||||||
quotedStringContent,
|
|
||||||
one<'"'>> {};
|
|
||||||
|
|
||||||
struct fieldParamValuePair : if_must<param,
|
|
||||||
opt<sep>,
|
|
||||||
one<'='>,
|
|
||||||
opt<sep>,
|
|
||||||
sor<quotedString,
|
|
||||||
unquotedString>> {};
|
|
||||||
struct fieldParamValuePairs : list<fieldParamValuePair, sep> {};
|
|
||||||
struct fieldParamValuePairsGrammar : must<opt<sep>,
|
|
||||||
opt<fieldParamValuePairs>,
|
|
||||||
opt<sep>,
|
|
||||||
tao::pegtl::eof> {};
|
|
||||||
|
|
||||||
struct fieldInferValueType : plus<upper> {};
|
|
||||||
struct fieldInferValuePrimaryValue : seq<// HACK: Because `number` matches empty string,
|
|
||||||
// ensure it is not empty.
|
|
||||||
at<sor<tao::pegtl::digit,
|
|
||||||
seq<one<'.'>>,
|
|
||||||
tao::pegtl::digit>>,
|
|
||||||
// END HACK.
|
|
||||||
number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>,
|
|
||||||
// Hackish: match anything until param-value pairs.
|
|
||||||
// Because the user may want to write something like
|
|
||||||
// "10k 30% 30mW w=0.4", but we care only about the
|
|
||||||
// "10k" and "w=0.4".
|
|
||||||
star<not_at<sep,
|
|
||||||
try_catch<fieldParamValuePairs>>,
|
|
||||||
any>> {};
|
|
||||||
struct fieldInferValue : sor<seq<fieldInferValueType,
|
|
||||||
opt<sep,
|
|
||||||
fieldParamValuePairs>>,
|
|
||||||
seq<opt<fieldInferValuePrimaryValue>,
|
|
||||||
opt<sep>,
|
|
||||||
opt<fieldParamValuePairs>>> {};
|
|
||||||
struct fieldInferValueGrammar : must<opt<sep>,
|
|
||||||
fieldInferValue,
|
|
||||||
opt<sep>,
|
|
||||||
tao::pegtl::eof> {};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename> inline constexpr const char* errorMessage = nullptr;
|
|
||||||
template <> inline constexpr auto errorMessage<opt<sep>> = "";
|
|
||||||
template <> inline constexpr auto errorMessage<opt<pinSequence>> = "";
|
|
||||||
template <> inline constexpr auto errorMessage<opt<sor<fieldInferValueType,
|
|
||||||
fieldInferValuePrimaryValue>>> = "";
|
|
||||||
template <> inline constexpr auto errorMessage<one<'='>> =
|
|
||||||
"expected '='";
|
|
||||||
template <> inline constexpr auto errorMessage<sor<quotedString,
|
|
||||||
unquotedString>> =
|
|
||||||
"expected quoted or unquoted string";
|
|
||||||
template <> inline constexpr auto errorMessage<fieldParamValuePairs> =
|
|
||||||
"expected parameter=value pairs";
|
|
||||||
template <> inline constexpr auto errorMessage<opt<fieldParamValuePairs>> = "";
|
|
||||||
template <> inline constexpr auto errorMessage<fieldInferValue> =
|
|
||||||
"expected parameter=value pairs, together possibly preceded by a type or primary value";
|
|
||||||
template <> inline constexpr auto errorMessage<tao::pegtl::eof> =
|
|
||||||
"expected end of string";
|
|
||||||
|
|
||||||
struct error
|
|
||||||
{
|
|
||||||
template <typename Rule> static constexpr bool raise_on_failure = false;
|
|
||||||
template <typename Rule> static constexpr auto message = errorMessage<Rule>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Rule> using control = must_if<error>::control<Rule>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class SIM_MODEL
|
class SIM_MODEL
|
||||||
|
@ -485,9 +390,6 @@ public:
|
||||||
|
|
||||||
static DEVICE_TYPE_ InferDeviceTypeFromRef( const std::string& aRef );
|
static DEVICE_TYPE_ InferDeviceTypeFromRef( const std::string& aRef );
|
||||||
|
|
||||||
static TYPE InferTypeFromRefAndValue( const std::string& aRef, const std::string& aValue,
|
|
||||||
int aSymbolPinCount );
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
||||||
|
|
||||||
|
@ -606,6 +508,8 @@ public:
|
||||||
// Can modifying a model parameter also modify other parameters?
|
// Can modifying a model parameter also modify other parameters?
|
||||||
virtual bool HasAutofill() const { return false; }
|
virtual bool HasAutofill() const { return false; }
|
||||||
|
|
||||||
|
virtual bool HasPrimaryValue() const { return false; }
|
||||||
|
|
||||||
void SetIsEnabled( bool aIsEnabled ) { m_isEnabled = aIsEnabled; }
|
void SetIsEnabled( bool aIsEnabled ) { m_isEnabled = aIsEnabled; }
|
||||||
bool IsEnabled() const { return m_isEnabled; }
|
bool IsEnabled() const { return m_isEnabled; }
|
||||||
|
|
||||||
|
@ -616,15 +520,17 @@ protected:
|
||||||
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
|
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
|
||||||
|
|
||||||
SIM_MODEL( TYPE aType );
|
SIM_MODEL( TYPE aType );
|
||||||
SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator );
|
SIM_MODEL( TYPE aType,
|
||||||
|
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator );
|
||||||
|
SIM_MODEL( TYPE aType,
|
||||||
|
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
|
||||||
|
std::unique_ptr<SIM_SERDE> aSerde );
|
||||||
|
|
||||||
virtual void CreatePins( unsigned aSymbolPinCount );
|
virtual void CreatePins( unsigned aSymbolPinCount );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteInferredDataFields( std::vector<T>& aFields, const std::string& aValue = "" ) const;
|
void WriteInferredDataFields( std::vector<T>& aFields, const std::string& aValue = "" ) const;
|
||||||
|
|
||||||
virtual std::string GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const;
|
|
||||||
|
|
||||||
std::string GenerateValueField( const std::string& aPairSeparator ) const;
|
std::string GenerateValueField( const std::string& aPairSeparator ) const;
|
||||||
std::string GenerateParamsField( const std::string& aPairSeparator ) const;
|
std::string GenerateParamsField( const std::string& aPairSeparator ) const;
|
||||||
void ParseParamsField( const std::string& aParamsField );
|
void ParseParamsField( const std::string& aParamsField );
|
||||||
|
@ -636,6 +542,7 @@ protected:
|
||||||
void InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
void InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||||
std::vector<PARAM> m_params;
|
std::vector<PARAM> m_params;
|
||||||
const SIM_MODEL* m_baseModel;
|
const SIM_MODEL* m_baseModel;
|
||||||
|
std::unique_ptr<SIM_SERDE> m_serde;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
|
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
|
||||||
|
@ -658,7 +565,6 @@ private:
|
||||||
|
|
||||||
std::string parseFieldFloatValue( std::string aFieldFloatValue );
|
std::string parseFieldFloatValue( std::string aFieldFloatValue );
|
||||||
|
|
||||||
virtual bool hasPrimaryValue() const { return false; }
|
|
||||||
virtual bool requiresSpiceModelLine() const;
|
virtual bool requiresSpiceModelLine() const;
|
||||||
|
|
||||||
virtual std::vector<std::string> getPinNames() const { return {}; }
|
virtual std::vector<std::string> getPinNames() const { return {}; }
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sim/sim_model_behavioral.h>
|
#include <sim/sim_model_behavioral.h>
|
||||||
|
#include <sim/sim_serde.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <boost/algorithm/string/trim.hpp>
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
@ -149,9 +150,9 @@ void SIM_MODEL_BEHAVIORAL::inferredReadDataFields( unsigned aSymbolPinCount,
|
||||||
{
|
{
|
||||||
ParsePinsField( aSymbolPinCount, GetFieldValue( aFields, PINS_FIELD ) );
|
ParsePinsField( aSymbolPinCount, GetFieldValue( aFields, PINS_FIELD ) );
|
||||||
|
|
||||||
if( ( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
if( ( m_serde->InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||||
GetFieldValue( aFields, VALUE_FIELD ),
|
GetFieldValue( aFields, VALUE_FIELD ),
|
||||||
aSymbolPinCount ) == GetType()
|
aSymbolPinCount ) == GetType()
|
||||||
&& parseValueField( GetFieldValue( aFields, VALUE_FIELD ) ) )
|
&& parseValueField( GetFieldValue( aFields, VALUE_FIELD ) ) )
|
||||||
// If Value is device type, this is an empty model
|
// If Value is device type, this is an empty model
|
||||||
|| GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
|| GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||||
|
|
|
@ -59,8 +59,8 @@ SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) :
|
||||||
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR_IDEAL>( *this ) )
|
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR_IDEAL>( *this ) )
|
||||||
{
|
{
|
||||||
static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "Ω" );
|
static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "Ω" );
|
||||||
static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" );
|
static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" );
|
||||||
static PARAM::INFO inductor = makeParamInfo( "l", "Inductance", "H" );
|
static PARAM::INFO inductor = makeParamInfo( "l", "Inductance", "H" );
|
||||||
|
|
||||||
switch( aType )
|
switch( aType )
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,12 +50,12 @@ public:
|
||||||
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
||||||
|
|
||||||
const PARAM* GetTunerParam() const override { return &GetParam( 0 ); }
|
const PARAM* GetTunerParam() const override { return &GetParam( 0 ); }
|
||||||
|
bool HasPrimaryValue() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||||
|
|
||||||
bool hasPrimaryValue() const override { return true; }
|
|
||||||
std::vector<std::string> getPinNames() const override { return { "+", "-" }; }
|
std::vector<std::string> getPinNames() const override { return { "+", "-" }; }
|
||||||
|
|
||||||
static PARAM::INFO makeParamInfo( std::string aName, std::string aDescription, std::string aUnit );
|
static PARAM::INFO makeParamInfo( std::string aName, std::string aDescription, std::string aUnit );
|
||||||
|
|
|
@ -49,13 +49,13 @@ public:
|
||||||
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
||||||
|
|
||||||
const PARAM* GetTunerParam() const override { return FindParam( "pos" ); }
|
const PARAM* GetTunerParam() const override { return FindParam( "pos" ); }
|
||||||
|
bool HasPrimaryValue() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||||
|
|
||||||
std::vector<std::string> getPinNames() const override { return { "+", "wiper", "-" }; }
|
std::vector<std::string> getPinNames() const override { return { "+", "wiper", "-" }; }
|
||||||
bool hasPrimaryValue() const override { return true; }
|
|
||||||
|
|
||||||
static const std::vector<PARAM::INFO> makeParamInfos();
|
static const std::vector<PARAM::INFO> makeParamInfos();
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sim/sim_model_raw_spice.h>
|
#include <sim/sim_model_raw_spice.h>
|
||||||
|
#include <sim/sim_serde.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
|
|
||||||
namespace SIM_MODEL_RAW_SPICE_PARSER
|
namespace SIM_MODEL_RAW_SPICE_PARSER
|
||||||
{
|
{
|
||||||
using namespace SIM_MODEL_GRAMMAR;
|
using namespace SIM_SERDE_GRAMMAR;
|
||||||
|
|
||||||
template <typename Rule> struct legacyPinSequenceSelector : std::false_type {};
|
template <typename Rule> struct legacyPinSequenceSelector : std::false_type {};
|
||||||
template <> struct legacyPinSequenceSelector<legacyPinNumber> : std::true_type {};
|
template <> struct legacyPinSequenceSelector<legacyPinNumber> : std::true_type {};
|
||||||
|
|
|
@ -198,6 +198,15 @@ std::string SPICE_GENERATOR_SOURCE::getParamValueString( const std::string& aPar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE_SOURCE::GenerateParamValuePair( const SIM_MODEL::PARAM& aParam ) const
|
||||||
|
{
|
||||||
|
if( aParam.value->ToString() == "0" )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return SIM_SERDE::GenerateParamValuePair( aParam );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType )
|
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType )
|
||||||
: SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR_SOURCE>( *this ) )
|
: SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR_SOURCE>( *this ) )
|
||||||
{
|
{
|
||||||
|
@ -253,15 +262,6 @@ void SIM_MODEL_SOURCE::SetParamValue( int aParamIndex, const SIM_VALUE& aValue )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string SIM_MODEL_SOURCE::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const
|
|
||||||
{
|
|
||||||
if( aParam.value->ToString() == "0" )
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return SIM_MODEL::GenerateParamValuePair( aParam, aIsFirst );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SIM_MODEL_SOURCE::inferredWriteDataFields( std::vector<T>& aFields ) const
|
void SIM_MODEL_SOURCE::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,12 +26,13 @@
|
||||||
#define SIM_MODEL_SOURCE_H
|
#define SIM_MODEL_SOURCE_H
|
||||||
|
|
||||||
#include <sim/sim_model.h>
|
#include <sim/sim_model.h>
|
||||||
|
#include <sim/sim_serde.h>
|
||||||
#include <sim/spice_generator.h>
|
#include <sim/spice_generator.h>
|
||||||
|
|
||||||
|
|
||||||
namespace SIM_MODEL_SOURCE_GRAMMAR
|
namespace SIM_MODEL_SOURCE_GRAMMAR
|
||||||
{
|
{
|
||||||
using namespace SIM_MODEL_GRAMMAR;
|
using namespace SIM_SERDE_GRAMMAR;
|
||||||
|
|
||||||
struct pwlSep : plus<space> {};
|
struct pwlSep : plus<space> {};
|
||||||
struct pwlValues : seq<opt<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>>,
|
struct pwlValues : seq<opt<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>>,
|
||||||
|
@ -54,7 +55,14 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getParamValueString( const std::string& aParamName,
|
std::string getParamValueString( const std::string& aParamName,
|
||||||
const std::string& aDefaultValue ) const;
|
const std::string& aDefaultValue ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SIM_SERDE_SOURCE : public SIM_SERDE
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::string GenerateParamValuePair( const SIM_MODEL::PARAM& aParam ) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,16 +77,13 @@ public:
|
||||||
void SetParamValue( int aParamIndex, const SIM_VALUE& aValue ) override;
|
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 true; }
|
||||||
protected:
|
|
||||||
std::string GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||||
|
|
||||||
|
|
||||||
bool hasPrimaryValue() const override { return true; }
|
|
||||||
std::vector<std::string> getPinNames() const override { return { "+", "-" }; }
|
std::vector<std::string> getPinNames() const override { return { "+", "-" }; }
|
||||||
|
|
||||||
static const std::vector<PARAM::INFO>& makeParamInfos( TYPE aType );
|
static const std::vector<PARAM::INFO>& makeParamInfos( TYPE aType );
|
||||||
|
|
|
@ -94,8 +94,19 @@ std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> SPICE_GENERATOR_SWITCH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE_SWITCH::GenerateParamValuePair( const SIM_MODEL::PARAM& aParam ) const
|
||||||
|
{
|
||||||
|
if( aParam.info.name == "ic" && aParam.value->ToString() == "none" )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return SIM_SERDE::GenerateParamValuePair( aParam );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) :
|
SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) :
|
||||||
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR_SWITCH>( *this ) )
|
SIM_MODEL( aType,
|
||||||
|
std::make_unique<SPICE_GENERATOR_SWITCH>( *this ),
|
||||||
|
std::make_unique<SIM_SERDE_SWITCH>( *this ) )
|
||||||
{
|
{
|
||||||
static std::vector<PARAM::INFO> vsw = makeSwVParamInfos();
|
static std::vector<PARAM::INFO> vsw = makeSwVParamInfos();
|
||||||
static std::vector<PARAM::INFO> isw = makeSwIParamInfos();
|
static std::vector<PARAM::INFO> isw = makeSwIParamInfos();
|
||||||
|
@ -121,15 +132,6 @@ SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string SIM_MODEL_SWITCH::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const
|
|
||||||
{
|
|
||||||
if( aParam.info.name == "ic" && aParam.value->ToString() == "none" )
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return SIM_MODEL::GenerateParamValuePair( aParam, aIsFirst );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_SWITCH::makeSwVParamInfos()
|
const std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_SWITCH::makeSwVParamInfos()
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <sim/sim_model.h>
|
#include <sim/sim_model.h>
|
||||||
#include <sim/spice_generator.h>
|
#include <sim/spice_generator.h>
|
||||||
|
#include <sim/sim_serde.h>
|
||||||
|
|
||||||
|
|
||||||
class SPICE_GENERATOR_SWITCH : public SPICE_GENERATOR
|
class SPICE_GENERATOR_SWITCH : public SPICE_GENERATOR
|
||||||
|
@ -40,14 +41,21 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SIM_SERDE_SWITCH : public SIM_SERDE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using SIM_SERDE::SIM_SERDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string GenerateParamValuePair( const SIM_MODEL::PARAM& aParam ) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class SIM_MODEL_SWITCH : public SIM_MODEL
|
class SIM_MODEL_SWITCH : public SIM_MODEL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SIM_MODEL_SWITCH( TYPE aType );
|
SIM_MODEL_SWITCH( TYPE aType );
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> getPinNames() const override
|
std::vector<std::string> getPinNames() const override
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Mikolaj Wielgus
|
||||||
|
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 3
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sim/sim_serde.h>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include <pegtl.hpp>
|
||||||
|
#include <pegtl/contrib/parse_tree.hpp>
|
||||||
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace SIM_SERDE_PARSER
|
||||||
|
{
|
||||||
|
using namespace SIM_SERDE_GRAMMAR;
|
||||||
|
|
||||||
|
template <typename Rule> struct fieldParamValuePairsSelector : std::false_type {};
|
||||||
|
template <> struct fieldParamValuePairsSelector<param> : std::true_type {};
|
||||||
|
template <> struct fieldParamValuePairsSelector<quotedStringContent> : std::true_type {};
|
||||||
|
template <> struct fieldParamValuePairsSelector<unquotedString> : std::true_type {};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Rule> struct pinSequenceSelector : std::false_type {};
|
||||||
|
template <> struct pinSequenceSelector<pinNumber> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename Rule> struct fieldInferValueSelector : std::false_type {};
|
||||||
|
template <> struct fieldInferValueSelector<fieldInferValueType> : std::true_type {};
|
||||||
|
template <> struct fieldInferValueSelector<fieldInferValuePrimaryValue> : std::true_type {};
|
||||||
|
template <> struct fieldInferValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> : std::true_type {};
|
||||||
|
template <> struct fieldInferValueSelector<fieldParamValuePairs> : std::true_type {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GenerateDevice() const
|
||||||
|
{
|
||||||
|
return m_model.GetDeviceTypeInfo().fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GenerateType() const
|
||||||
|
{
|
||||||
|
return m_model.GetTypeInfo().fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GenerateValue() const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
for( int i = 0; i < m_model.GetParamCount(); ++i )
|
||||||
|
{
|
||||||
|
const SIM_MODEL::PARAM& param = m_model.GetParam( i );
|
||||||
|
|
||||||
|
if( i == 0 && m_model.HasPrimaryValue() )
|
||||||
|
{
|
||||||
|
result.append( param.value->ToString() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( param.value->ToString() == "" )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.append( fmt::format( " {}", GenerateParamValuePair( param ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( result == "" )
|
||||||
|
result = m_model.GetDeviceTypeInfo().fieldValue;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GenerateParams() const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
for( int i = 0; i < m_model.GetParamCount(); ++i )
|
||||||
|
{
|
||||||
|
const SIM_MODEL::PARAM& param = m_model.GetParam( i );
|
||||||
|
|
||||||
|
if( param.value->ToString() == "" )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( i != 0 )
|
||||||
|
result.append( " " );
|
||||||
|
|
||||||
|
result.append( GenerateParamValuePair( param ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GeneratePins() const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
for( int i = 0; i < m_model.GetPinCount(); ++i )
|
||||||
|
{
|
||||||
|
const SIM_MODEL::PIN& pin = m_model.GetPin( i );
|
||||||
|
|
||||||
|
if( i != 0 )
|
||||||
|
result.append( " " );
|
||||||
|
|
||||||
|
if( pin.symbolPinNumber == "" )
|
||||||
|
result.append( "~" );
|
||||||
|
else
|
||||||
|
result.append( pin.symbolPinNumber );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GenerateEnable() const
|
||||||
|
{
|
||||||
|
return m_model.IsEnabled() ? "" : "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIM_MODEL::TYPE SIM_SERDE::ParseDeviceAndType( const std::string& aDevice,
|
||||||
|
const std::string& aType )
|
||||||
|
{
|
||||||
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||||
|
{
|
||||||
|
if( aType == SIM_MODEL::TypeInfo( type ).fieldValue
|
||||||
|
&& aDevice == SIM_MODEL::DeviceTypeInfo( SIM_MODEL::TypeInfo( type ).deviceType ).fieldValue )
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SIM_MODEL::TYPE::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SIM_SERDE::ParseValue( const std::string& aValue )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO: Don't call this multiple times.
|
||||||
|
tao::pegtl::string_input<> in( aValue, SIM_MODEL::VALUE_FIELD );
|
||||||
|
auto root = tao::pegtl::parse_tree::parse<SIM_SERDE_PARSER::fieldInferValueGrammar,
|
||||||
|
SIM_SERDE_PARSER::fieldInferValueSelector,
|
||||||
|
tao::pegtl::nothing,
|
||||||
|
SIM_SERDE_PARSER::control>( in );
|
||||||
|
|
||||||
|
for( const auto& node : root->children )
|
||||||
|
{
|
||||||
|
if( node->is_type<SIM_SERDE_PARSER::fieldInferValuePrimaryValue>() )
|
||||||
|
{
|
||||||
|
if( m_model.HasPrimaryValue() )
|
||||||
|
{
|
||||||
|
for( const auto& subnode : node->children )
|
||||||
|
{
|
||||||
|
if( subnode->is_type<SIM_SERDE_PARSER::number<SIM_VALUE::TYPE_FLOAT,
|
||||||
|
SIM_VALUE::NOTATION::SI>>() )
|
||||||
|
{
|
||||||
|
m_model.SetParamValue( 0, subnode->string() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR(
|
||||||
|
wxString::Format( _( "Simulation model of type '%s' cannot have a primary value (which is '%s') in Value field" ),
|
||||||
|
m_model.GetTypeInfo().fieldValue,
|
||||||
|
node->string() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( node->is_type<SIM_SERDE_PARSER::fieldParamValuePairs>() )
|
||||||
|
ParseParams( node->string() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( const tao::pegtl::parse_error& e )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( e.what() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SIM_SERDE::ParseParams( const std::string& aParams )
|
||||||
|
{
|
||||||
|
tao::pegtl::string_input<> in( aParams, SIM_MODEL::PARAMS_FIELD );
|
||||||
|
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Using parse tree instead of actions because we don't care about performance that much,
|
||||||
|
// and having a tree greatly simplifies things.
|
||||||
|
root = tao::pegtl::parse_tree::parse<
|
||||||
|
SIM_SERDE_PARSER::fieldParamValuePairsGrammar,
|
||||||
|
SIM_SERDE_PARSER::fieldParamValuePairsSelector,
|
||||||
|
tao::pegtl::nothing,
|
||||||
|
SIM_SERDE_PARSER::control>
|
||||||
|
( in );
|
||||||
|
}
|
||||||
|
catch( const tao::pegtl::parse_error& e )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( e.what() );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string paramName;
|
||||||
|
|
||||||
|
for( const auto& node : root->children )
|
||||||
|
{
|
||||||
|
if( node->is_type<SIM_SERDE_PARSER::param>() )
|
||||||
|
paramName = node->string();
|
||||||
|
// TODO: Do something with number<SIM_VALUE::TYPE_INT, ...>.
|
||||||
|
// It doesn't seem too useful?
|
||||||
|
else if( node->is_type<SIM_SERDE_PARSER::quotedStringContent>()
|
||||||
|
|| node->is_type<SIM_SERDE_PARSER::unquotedString>() )
|
||||||
|
{
|
||||||
|
wxASSERT( paramName != "" );
|
||||||
|
// TODO: Shouldn't be named "...fromSpiceCode" here...
|
||||||
|
|
||||||
|
m_model.SetParamValue( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI );
|
||||||
|
}
|
||||||
|
else if( node->is_type<SIM_SERDE_PARSER::quotedString>() )
|
||||||
|
{
|
||||||
|
std::string str = node->string();
|
||||||
|
|
||||||
|
// Unescape quotes.
|
||||||
|
boost::replace_all( str, "\\\"", "\"" );
|
||||||
|
|
||||||
|
m_model.SetParamValue( paramName, str, SIM_VALUE_GRAMMAR::NOTATION::SI );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SIM_SERDE::ParsePins( const std::string& aPins )
|
||||||
|
{
|
||||||
|
if( aPins == "" )
|
||||||
|
return;
|
||||||
|
|
||||||
|
tao::pegtl::string_input<> in( aPins, PINS_FIELD );
|
||||||
|
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
root = tao::pegtl::parse_tree::parse<SIM_SERDE_PARSER::pinSequenceGrammar,
|
||||||
|
SIM_SERDE_PARSER::pinSequenceSelector,
|
||||||
|
tao::pegtl::nothing,
|
||||||
|
SIM_SERDE_PARSER::control>( in );
|
||||||
|
}
|
||||||
|
catch( const tao::pegtl::parse_error& e )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( e.what() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( static_cast<int>( root->children.size() ) != m_model.GetPinCount() )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( wxString::Format( _( "%s describes %lu pins, expected %u" ),
|
||||||
|
PINS_FIELD,
|
||||||
|
root->children.size(),
|
||||||
|
m_model.GetPinCount() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int pinIndex = 0; pinIndex < static_cast<int>( root->children.size() ); ++pinIndex )
|
||||||
|
{
|
||||||
|
if( root->children.at( pinIndex )->string() == "~" )
|
||||||
|
m_model.SetPinSymbolPinNumber( pinIndex, "" );
|
||||||
|
else
|
||||||
|
m_model.SetPinSymbolPinNumber( pinIndex, root->children.at( pinIndex )->string() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SIM_SERDE::ParseEnable( const std::string& aEnable )
|
||||||
|
{
|
||||||
|
if( aEnable == "" )
|
||||||
|
return;
|
||||||
|
|
||||||
|
char c = boost::to_lower_copy( aEnable )[0];
|
||||||
|
|
||||||
|
if( c == 'n' || c == 'f' || c == '0' )
|
||||||
|
m_model.SetIsEnabled( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIM_MODEL::TYPE SIM_SERDE::InferTypeFromRefAndValue( const std::string& aRef,
|
||||||
|
const std::string& aValue,
|
||||||
|
int aSymbolPinCount )
|
||||||
|
{
|
||||||
|
std::string typeString;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tao::pegtl::string_input<> in( aValue, VALUE_FIELD );
|
||||||
|
auto root = tao::pegtl::parse_tree::parse<SIM_SERDE_PARSER::fieldInferValueGrammar,
|
||||||
|
SIM_SERDE_PARSER::fieldInferValueSelector,
|
||||||
|
tao::pegtl::nothing,
|
||||||
|
SIM_SERDE_PARSER::control>( in );
|
||||||
|
|
||||||
|
for( const auto& node : root->children )
|
||||||
|
{
|
||||||
|
if( node->is_type<SIM_SERDE_PARSER::fieldInferValueType>() )
|
||||||
|
typeString = node->string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( const tao::pegtl::parse_error& )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SIM_MODEL::DEVICE_TYPE_ deviceType = SIM_MODEL::InferDeviceTypeFromRef( aRef );
|
||||||
|
|
||||||
|
// Exception. Potentiometer model is determined from pin count.
|
||||||
|
if( deviceType == SIM_MODEL::DEVICE_TYPE_::R && aSymbolPinCount == 3 )
|
||||||
|
return SIM_MODEL::TYPE::R_POT;
|
||||||
|
|
||||||
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||||
|
{
|
||||||
|
if( SIM_MODEL::TypeInfo( type ).deviceType == deviceType
|
||||||
|
&& SIM_MODEL::TypeInfo( type ).fieldValue == typeString )
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SIM_MODEL::TYPE::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string SIM_SERDE::GenerateParamValuePair( const SIM_MODEL::PARAM& aParam ) const
|
||||||
|
{
|
||||||
|
std::string name = aParam.info.name;
|
||||||
|
|
||||||
|
// Because of collisions with instance parameters, we append some model parameters with "_".
|
||||||
|
if( boost::ends_with( aParam.info.name, "_" ) )
|
||||||
|
name = aParam.info.name.substr( 0, aParam.info.name.length() - 1 );
|
||||||
|
|
||||||
|
std::string value = aParam.value->ToString();
|
||||||
|
|
||||||
|
if( value.find( " " ) != std::string::npos )
|
||||||
|
value = fmt::format( "\"{}\"", value );
|
||||||
|
|
||||||
|
return fmt::format( "{}={}", aParam.info.name, value );
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Mikolaj Wielgus
|
||||||
|
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 3
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SIM_SERDE_H
|
||||||
|
#define SIM_SERDE_H
|
||||||
|
|
||||||
|
#include <sim/sim_model.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace SIM_SERDE_GRAMMAR
|
||||||
|
{
|
||||||
|
using namespace SIM_VALUE_GRAMMAR;
|
||||||
|
|
||||||
|
struct sep : plus<space> {};
|
||||||
|
|
||||||
|
|
||||||
|
struct legacyPinNumber : digits {};
|
||||||
|
struct legacyPinSequence : list<legacyPinNumber, sep> {};
|
||||||
|
|
||||||
|
struct legacyPinSequenceGrammar : must<legacyPinSequence,
|
||||||
|
tao::pegtl::eof> {};
|
||||||
|
|
||||||
|
|
||||||
|
struct pinNumber : plus<not_at<sep>, any> {};
|
||||||
|
struct pinSequence : list<pinNumber, sep> {};
|
||||||
|
struct pinSequenceGrammar : must<opt<sep>,
|
||||||
|
opt<pinSequence>,
|
||||||
|
opt<sep>,
|
||||||
|
tao::pegtl::eof> {};
|
||||||
|
|
||||||
|
struct param : plus<alnum> {};
|
||||||
|
|
||||||
|
struct unquotedString : plus<not_at<sep>, any> {};
|
||||||
|
struct quotedStringContent : star<not_at<one<'"'>>, any> {}; // TODO: Allow escaping '"'.
|
||||||
|
struct quotedString : seq<one<'"'>,
|
||||||
|
quotedStringContent,
|
||||||
|
one<'"'>> {};
|
||||||
|
|
||||||
|
struct fieldParamValuePair : if_must<param,
|
||||||
|
opt<sep>,
|
||||||
|
one<'='>,
|
||||||
|
opt<sep>,
|
||||||
|
sor<quotedString,
|
||||||
|
unquotedString>> {};
|
||||||
|
struct fieldParamValuePairs : list<fieldParamValuePair, sep> {};
|
||||||
|
struct fieldParamValuePairsGrammar : must<opt<sep>,
|
||||||
|
opt<fieldParamValuePairs>,
|
||||||
|
opt<sep>,
|
||||||
|
tao::pegtl::eof> {};
|
||||||
|
|
||||||
|
struct fieldInferValueType : plus<upper> {};
|
||||||
|
struct fieldInferValuePrimaryValue : seq<// HACK: Because `number` matches empty string,
|
||||||
|
// ensure it is not empty.
|
||||||
|
at<sor<tao::pegtl::digit,
|
||||||
|
seq<one<'.'>>,
|
||||||
|
tao::pegtl::digit>>,
|
||||||
|
// END HACK.
|
||||||
|
number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>,
|
||||||
|
// Hackish: match anything until param-value pairs.
|
||||||
|
// Because the user may want to write something like
|
||||||
|
// "10k 30% 30mW w=0.4", but we care only about the
|
||||||
|
// "10k" and "w=0.4".
|
||||||
|
star<not_at<sep,
|
||||||
|
try_catch<fieldParamValuePairs>>,
|
||||||
|
any>> {};
|
||||||
|
struct fieldInferValue : sor<seq<fieldInferValueType,
|
||||||
|
opt<sep,
|
||||||
|
fieldParamValuePairs>>,
|
||||||
|
seq<opt<fieldInferValuePrimaryValue>,
|
||||||
|
opt<sep>,
|
||||||
|
opt<fieldParamValuePairs>>> {};
|
||||||
|
struct fieldInferValueGrammar : must<opt<sep>,
|
||||||
|
fieldInferValue,
|
||||||
|
opt<sep>,
|
||||||
|
tao::pegtl::eof> {};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename> inline constexpr const char* errorMessage = nullptr;
|
||||||
|
template <> inline constexpr auto errorMessage<opt<sep>> = "";
|
||||||
|
template <> inline constexpr auto errorMessage<opt<pinSequence>> = "";
|
||||||
|
template <> inline constexpr auto errorMessage<opt<sor<fieldInferValueType,
|
||||||
|
fieldInferValuePrimaryValue>>> = "";
|
||||||
|
template <> inline constexpr auto errorMessage<one<'='>> =
|
||||||
|
"expected '='";
|
||||||
|
template <> inline constexpr auto errorMessage<sor<quotedString,
|
||||||
|
unquotedString>> =
|
||||||
|
"expected quoted or unquoted string";
|
||||||
|
template <> inline constexpr auto errorMessage<fieldParamValuePairs> =
|
||||||
|
"expected parameter=value pairs";
|
||||||
|
template <> inline constexpr auto errorMessage<opt<fieldParamValuePairs>> = "";
|
||||||
|
template <> inline constexpr auto errorMessage<fieldInferValue> =
|
||||||
|
"expected parameter=value pairs, together possibly preceded by a type or primary value";
|
||||||
|
template <> inline constexpr auto errorMessage<tao::pegtl::eof> =
|
||||||
|
"expected end of string";
|
||||||
|
|
||||||
|
struct error
|
||||||
|
{
|
||||||
|
template <typename Rule> static constexpr bool raise_on_failure = false;
|
||||||
|
template <typename Rule> static constexpr auto message = errorMessage<Rule>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Rule> using control = must_if<error>::control<Rule>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SerDe = Serializer-Deserializer
|
||||||
|
*/
|
||||||
|
class SIM_SERDE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto REFERENCE_FIELD = "Reference";
|
||||||
|
static constexpr auto VALUE_FIELD = "Value";
|
||||||
|
|
||||||
|
static constexpr auto DEVICE_TYPE_FIELD = "Sim_Device";
|
||||||
|
static constexpr auto TYPE_FIELD = "Sim_Type";
|
||||||
|
static constexpr auto PINS_FIELD = "Sim_Pins";
|
||||||
|
static constexpr auto PARAMS_FIELD = "Sim_Params";
|
||||||
|
static constexpr auto ENABLE_FIELD = "Sim_Enable";
|
||||||
|
|
||||||
|
SIM_SERDE( SIM_MODEL& aModel ) : m_model( aModel ) {}
|
||||||
|
|
||||||
|
std::string GenerateDevice() const;
|
||||||
|
std::string GenerateType() const;
|
||||||
|
std::string GenerateValue() const;
|
||||||
|
std::string GenerateParams() const;
|
||||||
|
std::string GeneratePins() const;
|
||||||
|
std::string GenerateEnable() const;
|
||||||
|
|
||||||
|
SIM_MODEL::TYPE ParseDeviceAndType( const std::string& aDevice,
|
||||||
|
const std::string& aType );
|
||||||
|
void ParseValue( const std::string& aValue );
|
||||||
|
void ParseParams( const std::string& aParams );
|
||||||
|
void ParsePins( const std::string& aPins );
|
||||||
|
void ParseEnable( const std::string& aEnable );
|
||||||
|
|
||||||
|
static SIM_MODEL::TYPE InferTypeFromRefAndValue( const std::string& aRef,
|
||||||
|
const std::string& aValue,
|
||||||
|
int aSymbolPinCount );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual std::string GenerateParamValuePair( const SIM_MODEL::PARAM& aParam ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SIM_MODEL& m_model;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SIM_SERDE_H
|
Loading…
Reference in New Issue