Allow inferred voltage/current sources to have a single float in Value
Update Opamp test to use this feature.
This commit is contained in:
parent
e30f059b43
commit
8a6a0ff7dc
|
@ -55,6 +55,11 @@ namespace SIM_MODEL_PARSER
|
|||
template <> struct fieldParamValuePairsSelector<unquotedString> : std::true_type {};
|
||||
|
||||
|
||||
template <typename Rule> struct fieldFloatValueSelector : std::false_type {};
|
||||
template <> struct fieldFloatValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>>
|
||||
: std::true_type {};
|
||||
|
||||
|
||||
template <typename Rule> struct pinSequenceSelector : std::false_type {};
|
||||
template <> struct pinSequenceSelector<pinNumber> : std::true_type {};
|
||||
}
|
||||
|
@ -1316,7 +1321,7 @@ void SIM_MODEL::ParseParamsField( const wxString& aParamsField )
|
|||
THROW_IO_ERROR( e.what() );
|
||||
}
|
||||
|
||||
wxString paramName = "";
|
||||
wxString paramName;
|
||||
|
||||
for( const auto& node : root->children )
|
||||
{
|
||||
|
@ -1516,26 +1521,52 @@ void SIM_MODEL::doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>
|
|||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL::InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields )
|
||||
void SIM_MODEL::InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields,
|
||||
bool aAllowOnlyFirstValue,
|
||||
bool aAllowParamValuePairs )
|
||||
{
|
||||
ParsePinsField( aSymbolPinCount, GetFieldValue( aFields, PINS_FIELD ) );
|
||||
|
||||
if( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) == GetType() )
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) != GetType() )
|
||||
{
|
||||
ParseParamsField( GetFieldValue( aFields, VALUE_FIELD ) );
|
||||
m_isInferred = true;
|
||||
// Not an inferred model. Nothing to do here.
|
||||
return;
|
||||
}
|
||||
else if( GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||
|
||||
wxString valueField = GetFieldValue( aFields, VALUE_FIELD );
|
||||
|
||||
if( aAllowParamValuePairs ) // The usual param-value pairs have precedence.
|
||||
{
|
||||
m_isInferred = true;
|
||||
try
|
||||
{
|
||||
ParseParamsField( GetFieldValue( aFields, VALUE_FIELD ) );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
if( aAllowOnlyFirstValue )
|
||||
SetParamValue( 0, parseFieldFloatValue( valueField ) );
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else if( aAllowOnlyFirstValue )
|
||||
{
|
||||
// This is reached only when model allows only the first value.
|
||||
SetParamValue( 0, parseFieldFloatValue( valueField ) );
|
||||
}
|
||||
|
||||
m_isInferred = true;
|
||||
}
|
||||
|
||||
template void SIM_MODEL::InferredReadDataFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields );
|
||||
const std::vector<SCH_FIELD>* aFields,
|
||||
bool aAllowOnlyFirstValue,
|
||||
bool aAllowParamValuePairs );
|
||||
template void SIM_MODEL::InferredReadDataFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields );
|
||||
const std::vector<LIB_FIELD>* aFields,
|
||||
bool aAllowOnlyFirstValue,
|
||||
bool aAllowParamValuePairs );
|
||||
|
||||
|
||||
template <typename T>
|
||||
|
@ -1589,6 +1620,26 @@ wxString SIM_MODEL::generateDisabledField() const
|
|||
}
|
||||
|
||||
|
||||
wxString SIM_MODEL::parseFieldFloatValue( wxString aFieldFloatValue )
|
||||
{
|
||||
try
|
||||
{
|
||||
tao::pegtl::string_input<> in( aFieldFloatValue.ToUTF8(), "Value" );
|
||||
auto root = tao::pegtl::parse_tree::parse<
|
||||
SIM_MODEL_PARSER::fieldFloatValueGrammar,
|
||||
SIM_MODEL_PARSER::fieldFloatValueSelector>
|
||||
( in );
|
||||
|
||||
return root->children[0]->string();
|
||||
}
|
||||
catch( const tao::pegtl::parse_error& )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Failed to infer model from Value '%s'" ),
|
||||
aFieldFloatValue ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SIM_MODEL::requiresSpiceModel() const
|
||||
{
|
||||
for( const PARAM& param : GetParams() )
|
||||
|
|
|
@ -579,7 +579,9 @@ protected:
|
|||
= SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
|
||||
template <typename T>
|
||||
void InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||
void InferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields,
|
||||
bool aAllowOnlyFirstValue = false,
|
||||
bool aAllowParamValuePairs = true );
|
||||
|
||||
wxString m_spiceCode;
|
||||
|
||||
|
@ -597,17 +599,18 @@ private:
|
|||
template <typename T>
|
||||
void doWriteFields( std::vector<T>& aFields ) const;
|
||||
|
||||
|
||||
virtual std::vector<wxString> getPinNames() const { return {}; }
|
||||
|
||||
wxString generateDeviceTypeField() const;
|
||||
wxString generateTypeField() const;
|
||||
|
||||
wxString generatePinsField() const;
|
||||
wxString generateDisabledField() const;
|
||||
|
||||
wxString parseFieldFloatValue( wxString aFieldFloatValue );
|
||||
|
||||
virtual bool requiresSpiceModel() const;
|
||||
|
||||
virtual std::vector<wxString> getPinNames() const { return {}; }
|
||||
|
||||
|
||||
const SIM_MODEL* m_baseModel;
|
||||
|
||||
|
|
|
@ -29,16 +29,6 @@
|
|||
using PARAM = SIM_MODEL::PARAM;
|
||||
|
||||
|
||||
namespace SIM_MODEL_PARSER
|
||||
{
|
||||
using namespace SIM_MODEL_GRAMMAR;
|
||||
|
||||
template <typename Rule> struct fieldFloatValueSelector : std::false_type {};
|
||||
template <> struct fieldFloatValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>>
|
||||
: std::true_type {};
|
||||
};
|
||||
|
||||
|
||||
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType )
|
||||
: SIM_MODEL( aType ),
|
||||
m_isInferred( false )
|
||||
|
@ -64,7 +54,7 @@ void SIM_MODEL_IDEAL::ReadDataSchFields( unsigned aSymbolPinCount,
|
|||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
InferredReadDataFields( aSymbolPinCount, aFields, true, false );
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,7 +64,7 @@ void SIM_MODEL_IDEAL::ReadDataLibFields( unsigned aSymbolPinCount,
|
|||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
InferredReadDataFields( aSymbolPinCount, aFields, true, false );
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,42 +106,6 @@ wxString SIM_MODEL_IDEAL::GenerateSpiceItemLine( const wxString& aRefName,
|
|||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_IDEAL::inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields )
|
||||
{
|
||||
ParsePinsField( aSymbolPinCount, GetFieldValue( aFields, PINS_FIELD ) );
|
||||
|
||||
if( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) == GetType() )
|
||||
{
|
||||
try
|
||||
{
|
||||
wxString value = GetFieldValue( aFields, VALUE_FIELD );
|
||||
|
||||
tao::pegtl::string_input<> in( value.ToUTF8(), "Value" );
|
||||
auto root = tao::pegtl::parse_tree::parse<
|
||||
SIM_MODEL_PARSER::fieldFloatValueGrammar,
|
||||
SIM_MODEL_PARSER::fieldFloatValueSelector>
|
||||
( in );
|
||||
|
||||
// The grammar and selector must guarantee having at least one child.
|
||||
SetParamValue( 0, root->children[0]->string() );
|
||||
}
|
||||
catch( const tao::pegtl::parse_error& )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Failed to infer model from Value '%s'" ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) );
|
||||
}
|
||||
|
||||
m_isInferred = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if( GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||
m_isInferred = true;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_IDEAL::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||
{
|
||||
|
|
|
@ -47,9 +47,6 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||
|
||||
template <typename T>
|
||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void SIM_MODEL_SOURCE::ReadDataSchFields( unsigned aSymbolPinCount,
|
|||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
InferredReadDataFields( aSymbolPinCount, aFields );
|
||||
InferredReadDataFields( aSymbolPinCount, aFields, true );
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ void SIM_MODEL_SOURCE::ReadDataLibFields( unsigned aSymbolPinCount,
|
|||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
InferredReadDataFields( aSymbolPinCount, aFields );
|
||||
InferredReadDataFields( aSymbolPinCount, aFields, true );
|
||||
}
|
||||
|
||||
|
||||
|
@ -242,8 +242,12 @@ bool SIM_MODEL_SOURCE::SetParamValue( unsigned aParamIndex, const wxString& aVal
|
|||
// them out automatically. If a value is nulled, delete everything after it.
|
||||
if( aValue == "" )
|
||||
{
|
||||
for( int paramIndex = aParamIndex; paramIndex < GetParamCount(); ++paramIndex )
|
||||
for( int paramIndex = static_cast<int>( aParamIndex );
|
||||
paramIndex < GetParamCount();
|
||||
++paramIndex )
|
||||
{
|
||||
SIM_MODEL::SetParamValue( paramIndex, "", aNotation );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -63,7 +63,8 @@ public:
|
|||
const std::vector<wxString>& aPinNetNames ) const override;
|
||||
|
||||
bool SetParamValue( unsigned aParamIndex, const wxString& aValue,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation ) override;
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI )
|
||||
override;
|
||||
|
||||
bool HasAutofill() const override { return true; }
|
||||
|
||||
|
|
|
@ -265,9 +265,11 @@
|
|||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"net_colors": null
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": []
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(kicad_sch (version 20220622) (generator eeschema)
|
||||
(kicad_sch (version 20220820) (generator eeschema)
|
||||
|
||||
(uuid fd5567b0-04f0-4d9e-b647-1775367d8ff4)
|
||||
|
||||
|
@ -404,18 +404,6 @@
|
|||
(property "Datasheet" "~" (id 3) (at 153.67 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Device" "V" (id 4) (at 153.67 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Type" "DC" (id 5) (at 153.67 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Pins" "1 2" (id 6) (at 153.67 76.2 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Params" "dc=5" (id 7) (at 160.02 78.74 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(pin "1" (uuid 885c89aa-c780-4741-b398-9d4b8e38f094))
|
||||
(pin "2" (uuid 8a2dca0c-b99f-4109-a426-af5e80ea91fe))
|
||||
)
|
||||
|
@ -528,18 +516,6 @@
|
|||
(property "Datasheet" "~" (id 3) (at 153.67 101.6 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Device" "V" (id 4) (at 153.67 101.6 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Type" "DC" (id 5) (at 153.67 101.6 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Pins" "1 2" (id 6) (at 153.67 101.6 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Sim_Params" "dc=5" (id 7) (at 160.02 104.14 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(pin "1" (uuid 62bdf880-7061-4b86-be3a-09bf959fae21))
|
||||
(pin "2" (uuid 9bd26aa2-337b-4c5a-a9de-bdab770672a9))
|
||||
)
|
||||
|
@ -591,10 +567,10 @@
|
|||
(reference "U1") (unit 1) (value "OPAMP") (footprint "")
|
||||
)
|
||||
(path "/383ea298-1cb3-473e-8fce-19d3c7ac3912"
|
||||
(reference "V2") (unit 1) (value "VDC") (footprint "")
|
||||
(reference "V2") (unit 1) (value "5") (footprint "")
|
||||
)
|
||||
(path "/d2018f30-5def-453e-85fe-dac327cfbe9b"
|
||||
(reference "V3") (unit 1) (value "VDC") (footprint "")
|
||||
(reference "V3") (unit 1) (value "5") (footprint "")
|
||||
)
|
||||
(path "/10f44001-5f65-44eb-a535-b7b3c67d5b83"
|
||||
(reference "VSIN1") (unit 1) (value "ampl=500m f=1k") (footprint "")
|
||||
|
|
|
@ -299,6 +299,8 @@ BOOST_AUTO_TEST_CASE( Opamp )
|
|||
|
||||
BOOST_AUTO_TEST_CASE( NpnCeAmp )
|
||||
{
|
||||
// This test intentionally uses non-inferred voltage sources to test them.
|
||||
|
||||
TestNetlist( "npn_ce_amp" );
|
||||
TestTranPoint( 900e-6, { { "V(/in)", 0 }, { "V(/out)", 5.32 } } );
|
||||
TestTranPoint( 925e-6, { { "V(/in)", 10e-3 }, { "V(/out)", 5.30 } } );
|
||||
|
|
Loading…
Reference in New Issue