Clean up (and better comment) referential model handling.

This commit is contained in:
Jeff Young 2024-09-02 09:49:06 +01:00
parent ee77d06be7
commit c7859e7ed7
8 changed files with 36 additions and 28 deletions

View File

@ -376,7 +376,6 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
case TYPE::KIBIS_DRIVER_PRBS: return { "X" };
case TYPE::NONE:
case TYPE::REFERENTIAL:
case TYPE::RAWSPICE: return {};
default: wxFAIL; return {};

View File

@ -280,7 +280,6 @@ public:
I_RANDPOISSON,
I_BEHAVIORAL,
REFERENTIAL,
SUBCKT,
XSPICE,

View File

@ -55,12 +55,11 @@ std::string SPICE_GENERATOR_SPICE::Preview( const SPICE_ITEM& aItem ) const
std::unique_ptr<SIM_MODEL_SPICE> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode,
bool aSkipReferential,
REPORTER& aReporter )
bool aFirstPass, REPORTER& aReporter )
{
SIM_MODEL::TYPE type = SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode, aSkipReferential );
SIM_MODEL::TYPE type = SIM_MODEL::TYPE::NONE;
if( type == SIM_MODEL::TYPE::REFERENTIAL )
if( !SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode, &type, aFirstPass ) )
return nullptr;
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );

View File

@ -49,8 +49,7 @@ public:
static std::unique_ptr<SIM_MODEL_SPICE> Create( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode,
bool aSkipReferential,
REPORTER& aReporter );
bool aFirstPass, REPORTER& aReporter );
SIM_MODEL_SPICE( TYPE aType,
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator );

View File

@ -128,10 +128,10 @@ void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER& aRepor
}
auto createModel =
[&]( int ii, bool aSkipReferential )
[&]( int ii, bool firstPass )
{
m_library.m_models[ii] = SIM_MODEL_SPICE::Create( m_library, modelQueue[ii].second,
aSkipReferential, aReporter );
firstPass, aReporter );
};
// Read all self-contained models in parallel
@ -145,7 +145,7 @@ void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER& aRepor
} );
tp.wait_for_tasks();
// Now read all referential models in order.
// Now read all models that might refer to other models in order.
for( int ii = 0; ii < (int) modelQueue.size(); ++ii )
{
if( !m_library.m_models[ii] )

View File

@ -41,7 +41,7 @@ public:
virtual ~SPICE_LIBRARY_PARSER()
{};
virtual void ReadFile( const wxString& aFilePath, REPORTER& aReporter );
virtual void ReadFile( const wxString& aFilePath, REPORTER& firstPass );
protected:
void parseFile( const wxString& aFilePath, REPORTER& aReporter,

View File

@ -59,9 +59,11 @@ namespace SIM_MODEL_SPICE_PARSER
}
SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode, bool aSkipReferential )
bool SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary, const std::string& aSpiceCode,
SIM_MODEL::TYPE* aType, bool aFirstPass )
{
*aType = SIM_MODEL::TYPE::NONE;
tao::pegtl::string_input<> in( aSpiceCode, "Spice_Code" );
std::unique_ptr<tao::pegtl::parse_tree::node> root;
@ -76,15 +78,17 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
catch( const tao::pegtl::parse_error& e )
{
wxLogTrace( traceSpiceModelParser, wxS( "%s" ), e.what() );
return SIM_MODEL::TYPE::NONE;
return true;
}
for( const auto& node : root->children )
{
if( node->is_type<SIM_MODEL_SPICE_PARSER::dotModelAko>() )
{
if( aSkipReferential )
return SIM_MODEL::TYPE::REFERENTIAL;
// The first pass of model loading is done in parallel, so we can't (yet) look
// up our reference model.
if( aFirstPass )
return false;
std::string modelName = node->children.at( 0 )->string();
std::string akoName = node->children.at( 1 )->string();
@ -98,7 +102,8 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
modelName ) );
}
return sourceModel->GetType();
*aType = sourceModel->GetType();
return true;
}
else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotModel>() )
{
@ -119,7 +124,10 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
SIM_MODEL::TYPE type = ReadTypeFromSpiceStrings( typeString );
if( type != SIM_MODEL::TYPE::RAWSPICE )
return type;
{
*aType = type;
return true;
}
}
else if( subnode->is_type<SIM_MODEL_SPICE_PARSER::param>() )
{
@ -137,7 +145,7 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
else
{
wxFAIL_MSG( "Unhandled parse tree subnode" );
return SIM_MODEL::TYPE::NONE;
return true;
}
}
@ -145,24 +153,28 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
// `version` variables into account too. This is suboptimal since we read the model
// twice this way, and moreover the code is now somewhat duplicated.
return ReadTypeFromSpiceStrings( typeString, level, version, false );
*aType = ReadTypeFromSpiceStrings( typeString, level, version, false );
return true;
}
else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotSubckt>() )
{
if( aSkipReferential )
return SIM_MODEL::TYPE::REFERENTIAL;
// The first pass of model loading is done in parallel, so we can't (yet) refer to
// any other models in a subcircuit.
if( aFirstPass )
return false;
return SIM_MODEL::TYPE::SUBCKT;
*aType = SIM_MODEL::TYPE::SUBCKT;
return true;
}
else
{
wxFAIL_MSG( "Unhandled parse tree node" );
return SIM_MODEL::TYPE::NONE;
return true;
}
}
wxFAIL_MSG( "Could not derive type from SPICE code" );
return SIM_MODEL::TYPE::NONE;
return true;
}

View File

@ -34,8 +34,8 @@ class SIM_LIBRARY_SPICE;
class SPICE_MODEL_PARSER
{
public:
static SIM_MODEL::TYPE ReadType( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode, bool aSkipReferential );
static bool ReadType( const SIM_LIBRARY_SPICE& aLibrary, const std::string& aSpiceCode,
SIM_MODEL::TYPE* aType, bool aFirstPass );
SPICE_MODEL_PARSER( SIM_MODEL_SPICE& aModel ) : m_model( aModel ) {}
virtual ~SPICE_MODEL_PARSER() = default;