Re-enable sim model ERC testing.

This commit is contained in:
Jeff Young 2023-01-02 22:47:46 +00:00
parent c2e7524cb6
commit 7f35323416
8 changed files with 112 additions and 72 deletions

View File

@ -43,8 +43,7 @@
#include <drawing_sheet/ds_draw_item.h>
#include <drawing_sheet/ds_proxy_view_item.h>
#include <wx/ffile.h>
#include "sim/sim_model.h"
#include <sim/sim_lib_mgr.h>
/* ERC tests :
@ -1013,8 +1012,11 @@ int ERC_TESTER::TestOffGridEndpoints( int aGridSize )
int ERC_TESTER::TestSimModelIssues()
{
SCH_SHEET_LIST sheets = m_schematic->GetSheets();
int err_count = 0;
wxString msg;
WX_STRING_REPORTER reporter( &msg );
SCH_SHEET_LIST sheets = m_schematic->GetSheets();
int err_count = 0;
SIM_LIB_MGR libMgr( &m_schematic->Prj(), &reporter );
for( SCH_SHEET_PATH& sheet : sheets )
{
@ -1022,18 +1024,16 @@ int ERC_TESTER::TestSimModelIssues()
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
// Reset for each symbol
msg.Clear();
try
{
/* JEY TODO
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( &sheet, symbol, true );
*/
}
catch( IO_ERROR& e )
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
SIM_LIBRARY::MODEL model = libMgr.CreateModel( &sheet, *symbol );
if( !msg.IsEmpty() )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMULATION_MODEL );
ercItem->SetErrorMessage( e.Problem() );
ercItem->SetErrorMessage( msg );
ercItem->SetItems( symbol );
markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );

View File

@ -258,6 +258,8 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
spiceItem.fields.back().SetText( pinMap );
}
// JEY TODO: move from try/catch to REPORTER interface...
// readModel() is the only one that throws, and it won't if m_libMgr has a REPORTER
try
{
readRefName( sheet, *symbol, spiceItem, refNames );

View File

@ -36,8 +36,9 @@
#include <sim/sim_model.h>
#include <sim/sim_model_ideal.h>
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj ) :
m_project( aPrj )
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter ) :
m_project( aPrj ),
m_reporter( aReporter )
{
}
@ -146,7 +147,7 @@ SIM_LIBRARY& SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER* aR
SIM_MODEL& SIM_LIB_MGR::CreateModel( SIM_MODEL::TYPE aType, const std::vector<LIB_PIN*>& aPins )
{
m_models.push_back( SIM_MODEL::Create( aType, aPins ) );
m_models.push_back( SIM_MODEL::Create( aType, aPins, m_reporter ) );
return *m_models.back();
}
@ -154,7 +155,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SIM_MODEL::TYPE aType, const std::vector<LI
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins )
{
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins ) );
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins, m_reporter ) );
return *m_models.back();
}
@ -164,7 +165,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields )
{
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins, aFields ) );
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins, aFields, m_reporter ) );
return *m_models.back();
}
@ -254,7 +255,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<T>& aFields,
}
else
{
m_models.push_back( SIM_MODEL::Create( aFields, aPins ) );
m_models.push_back( SIM_MODEL::Create( aFields, aPins, m_reporter ) );
return { baseModelName, *m_models.back() };
}
}
@ -273,6 +274,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
{
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
SIM_LIBRARY* library = nullptr;
wxString msg;
std::function<std::string(const std::string&, const std::string&)> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 );
@ -284,28 +286,42 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
}
catch( const IO_ERROR& e )
{
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model library '%s': %s" ),
path,
e.What() ) );
msg.Printf( _( "Error loading simulation model library '%s': %s" ),
path,
e.What() );
if( m_reporter )
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
else
THROW_IO_ERROR( msg );
}
if( aBaseModelName == "" )
{
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model: no '%s' field" ),
SIM_LIBRARY::NAME_FIELD ) );
msg.Printf( _( "Error loading simulation model: no '%s' field" ),
SIM_LIBRARY::NAME_FIELD );
if( m_reporter )
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
else
THROW_IO_ERROR( msg );
}
SIM_MODEL* baseModel = library->FindModel( aBaseModelName );
if( !baseModel )
{
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model: could not find "
"base model '%s' in library '%s'" ),
aBaseModelName,
path ) );
msg.Printf( _( "Error loading simulation model: could not find base model '%s' in library '%s'" ),
aBaseModelName,
path );
if( m_reporter )
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
else
THROW_IO_ERROR( msg );
}
m_models.push_back( SIM_MODEL::Create( *baseModel, aPins, aFields ) );
m_models.push_back( SIM_MODEL::Create( *baseModel, aPins, aFields, m_reporter ) );
return { aBaseModelName, *m_models.back() };
}

View File

@ -40,7 +40,7 @@ class SCH_SYMBOL;
class SIM_LIB_MGR
{
public:
SIM_LIB_MGR( const PROJECT* aPrj );
SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter = nullptr );
virtual ~SIM_LIB_MGR() = default;
void Clear();
@ -80,6 +80,7 @@ public:
private:
const PROJECT* m_project;
REPORTER* m_reporter;
std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries;
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
};

View File

@ -47,7 +47,7 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
{
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins ) );
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins, nullptr ) );
m_modelNames.emplace_back( kcomp.m_name );
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );

View File

@ -443,7 +443,8 @@ void SIM_MODEL::WriteFields( std::vector<LIB_FIELD>& aFields ) const
}
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_PIN*>& aPins )
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter )
{
std::unique_ptr<SIM_MODEL> model = Create( aType );
@ -452,9 +453,12 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_
// Passing nullptr to ReadDataFields will make it act as if all fields were empty.
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
}
catch( ... )
catch( IO_ERROR& err )
{
// Shouldn't happen with nothing to read from fields
if( aReporter )
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
else
DisplayErrorMessage( nullptr, err.What() );
}
return model;
@ -462,7 +466,8 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins)
const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter )
{
std::unique_ptr<SIM_MODEL> model;
@ -480,7 +485,10 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
}
catch( IO_ERROR& err )
{
DisplayErrorMessage( nullptr, err.What() );
if( aReporter )
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
else
DisplayErrorMessage( nullptr, err.What() );
}
return model;
@ -490,7 +498,8 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
template <typename T>
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields )
const std::vector<T>& aFields,
REPORTER* aReporter )
{
TYPE type = ReadTypeFromFields( aFields );
@ -514,7 +523,10 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
}
catch( IO_ERROR& err )
{
DisplayErrorMessage( nullptr, err.What() );
if( aReporter )
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
else
DisplayErrorMessage( nullptr, err.What() );
}
return model;
@ -522,16 +534,19 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins,
const std::vector<SCH_FIELD>& aFields );
const std::vector<SCH_FIELD>& aFields,
REPORTER* aReporter );
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins,
const std::vector<LIB_FIELD>& aFields );
const std::vector<LIB_FIELD>& aFields,
REPORTER* aReporter );
template <typename T>
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
const std::vector<LIB_PIN*>& aPins )
const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter )
{
TYPE type = ReadTypeFromFields( aFields );
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
@ -560,7 +575,10 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
catch( const IO_ERROR& err )
{
// We own the pin syntax, so if we can't parse it then there's an error, full stop.
DisplayErrorMessage( nullptr, err.What() );
if( aReporter )
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
else
DisplayErrorMessage( nullptr, err.What() );
}
}
@ -568,9 +586,11 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
}
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<SCH_FIELD>& aFields,
const std::vector<LIB_PIN*>& aPins );
const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter );
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<LIB_FIELD>& aFields,
const std::vector<LIB_PIN*>& aPins );
const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter );
template <typename T>
@ -1529,40 +1549,35 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
}
wxString spiceDeviceType = spiceDeviceInfo.m_Text.Trim( true ).Trim( false );
wxString spiceLib = spiceLibInfo.m_Text.Trim( true ).Trim( false );
wxString spiceModel = spiceModelInfo.m_Text.Trim( true ).Trim( false );
bool libraryModel = false;
bool inferredModel = false;
bool internalModel = false;
if( !spiceLibInfo.IsEmpty() )
if( !spiceLib.IsEmpty() )
{
SIM_LIB_MGR libMgr( aProject );
wxString msg;
WX_STRING_REPORTER reporter( &msg );
SIM_LIB_MGR libMgr( aProject, &reporter );
std::vector<T_field> emptyFields;
try
SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLib, spiceModel.ToStdString(),
emptyFields, sourcePins );
libraryModel = !reporter.HasMessage(); // Otherwise we'll fall back to raw spice model
if( pinMapInfo.IsEmpty() )
{
std::vector<T_field> emptyFields;
SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLibInfo.m_Text,
spiceModel.ToStdString(),
emptyFields, sourcePins );
// Try to generate a default pin map from the SIM_MODEL's pins; if that fails,
// generate one from the symbol's pins
libraryModel = true;
model.model.SIM_MODEL::createPins( sourcePins );
pinMapInfo.m_Text = wxString( model.model.Serializer().GeneratePins() );
if( pinMapInfo.IsEmpty() )
{
// Try to generate a default pin map from the SIM_MODEL's pins; if that fails,
// generate one from the symbol's pins
model.model.SIM_MODEL::createPins( sourcePins );
pinMapInfo.m_Text = wxString( model.model.Serializer().GeneratePins() );
if( pinMapInfo.IsEmpty() )
pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins );
}
}
catch( ... )
{
// Fall back to raw spice model
pinMapInfo.m_Text = generateDefaultPinMapFromSymbol( sourcePins );
}
}
else if( ( spiceDeviceType == "R" || spiceDeviceType == "L" || spiceDeviceType == "C" )
@ -1670,14 +1685,14 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
}
else // Insert a raw spice model as a substitute.
{
if( spiceDeviceType.IsEmpty() && spiceLibInfo.IsEmpty() )
if( spiceDeviceType.IsEmpty() && spiceLib.IsEmpty() )
{
spiceParamsInfo = spiceModelInfo;
}
else
{
spiceParamsInfo.m_Text.Printf( wxT( "type=\"%s\" model=\"%s\" lib=\"%s\"" ),
spiceDeviceType, spiceModel, spiceLibInfo.m_Text );
spiceDeviceType, spiceModel, spiceLib );
}
T_field deviceField = spiceDeviceInfo.CreateField( &aSymbol, SIM_MODEL::DEVICE_TYPE_FIELD );

View File

@ -30,6 +30,7 @@
#include <map>
#include <utility>
#include <reporter.h>
#include <sch_field.h>
#include <lib_field.h>
@ -400,19 +401,23 @@ public:
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, const std::vector<LIB_PIN*>& aPins );
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter );
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins );
const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter );
template <typename T>
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel,
const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields );
const std::vector<T>& aFields,
REPORTER* aReporter );
template <typename T>
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields,
const std::vector<LIB_PIN*>& aPins );
const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter );
template <typename T>
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName,

View File

@ -874,6 +874,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
LIB_PIN* pin = static_cast<SCH_PIN*>( item )->GetLibPin();
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
// JEY TODO: move to reporter interface instead of try/catch....
SIM_LIB_MGR mgr( &m_frame->Prj() );
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;