Ibis differential and PRBS models

This commit is contained in:
Fabien Corona 2022-09-29 08:35:01 +00:00 committed by Mikolaj Wielgus
parent 8ae48bb093
commit 7e486327d9
11 changed files with 302 additions and 78 deletions

View File

@ -524,7 +524,26 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
try try
{ {
m_library->ReadFile( std::string( absolutePath.ToUTF8() ) ); if( IsIbisLoaded() )
{
wxString ibisTypeString = SIM_MODEL::GetFieldValue( &m_fields, SIM_MODEL::TYPE_FIELD );
SIM_MODEL::TYPE ibisType = SIM_MODEL::TYPE::KIBIS_DEVICE;
if( ibisTypeString == "IBISDRIVER" )
ibisType = SIM_MODEL::TYPE::KIBIS_DRIVER;
else if( ibisTypeString == "IBISDIFFDRIVER" )
ibisType = SIM_MODEL::TYPE::KIBIS_DIFFDRIVER;
else if( ibisTypeString == "IBISDIFFDEVICE" )
ibisType = SIM_MODEL::TYPE::KIBIS_DIFFDEVICE;
std::dynamic_pointer_cast<SIM_LIBRARY_KIBIS>( m_library )
->ReadFile( std::string( absolutePath.ToUTF8() ), ibisType );
}
else
{
m_library->ReadFile( std::string( absolutePath.ToUTF8() ) );
}
} }
catch( const IO_ERROR& e ) catch( const IO_ERROR& e )
{ {
@ -1010,8 +1029,9 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
&& typeDescription == SIM_MODEL::TypeInfo( type ).description ) && typeDescription == SIM_MODEL::TypeInfo( type ).description )
{ {
if( IsIbisLoaded() if( IsIbisLoaded()
&& ( type == SIM_MODEL::TYPE::KIBIS_DEVICE && ( type == SIM_MODEL::TYPE::KIBIS_DEVICE || type == SIM_MODEL::TYPE::KIBIS_DRIVER
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER ) ) || type == SIM_MODEL::TYPE::KIBIS_DIFFDRIVER
|| type == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE ) )
{ {
std::shared_ptr<SIM_MODEL_KIBIS> kibismodel = std::shared_ptr<SIM_MODEL_KIBIS> kibismodel =
std::dynamic_pointer_cast<SIM_MODEL_KIBIS>( std::dynamic_pointer_cast<SIM_MODEL_KIBIS>(

View File

@ -273,6 +273,8 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
switch( type ) switch( type )
{ {
case SIM_MODEL::TYPE::KIBIS_DIFFDEVICE:
case SIM_MODEL::TYPE::KIBIS_DIFFDRIVER:
case SIM_MODEL::TYPE::KIBIS_DEVICE: case SIM_MODEL::TYPE::KIBIS_DEVICE:
case SIM_MODEL::TYPE::KIBIS_DRIVER: break; case SIM_MODEL::TYPE::KIBIS_DRIVER: break;
default: default:
@ -329,6 +331,10 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
case SIM_MODEL::TYPE::KIBIS_DEVICE: case SIM_MODEL::TYPE::KIBIS_DEVICE:
kpin->writeSpiceDevice( &modelData, modelName, *kmodel, kparams ); kpin->writeSpiceDevice( &modelData, modelName, *kmodel, kparams );
break; break;
case SIM_MODEL::TYPE::KIBIS_DIFFDEVICE:
kpin->writeSpiceDiffDevice( &modelData, modelName, *kmodel, kparams );
break;
case SIM_MODEL::TYPE::KIBIS_DIFFDRIVER:
case SIM_MODEL::TYPE::KIBIS_DRIVER: case SIM_MODEL::TYPE::KIBIS_DRIVER:
{ {
mparam = spiceItem.model->FindParam( "wftype" ); mparam = spiceItem.model->FindParam( "wftype" );
@ -369,6 +375,39 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
->Get() ->Get()
.value_or( 0 ) ); .value_or( 0 ) );
} }
if( paramValue == "prbs" )
{
kparams.m_waveform = static_cast<KIBIS_WAVEFORM*>(
new KIBIS_WAVEFORM_PRBS() );
mparam = spiceItem.model->FindParam( "bitrate" );
if( mparam )
static_cast<KIBIS_WAVEFORM_PRBS*>( kparams.m_waveform )
->m_bitrate = static_cast<double>(
std::dynamic_pointer_cast<SIM_VALUE_FLOAT>( mparam->value )
->Get()
.value_or( 1 ) );
mparam = spiceItem.model->FindParam( "nbits" );
if( mparam )
static_cast<KIBIS_WAVEFORM_PRBS*>( kparams.m_waveform )
->m_bits = static_cast<double>(
std::dynamic_pointer_cast<SIM_VALUE_FLOAT>( mparam->value )
->Get()
.value_or( 1 ) );
mparam = spiceItem.model->FindParam( "delay" );
if( mparam )
static_cast<KIBIS_WAVEFORM_PRBS*>( kparams.m_waveform )
->m_delay = static_cast<double>(
std::dynamic_pointer_cast<SIM_VALUE_FLOAT>( mparam->value )
->Get()
.value_or( 0 ) );
}
else if( paramValue == "stuck high" ) else if( paramValue == "stuck high" )
{ {
kparams.m_waveform = kparams.m_waveform =
@ -385,7 +424,11 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z() ); static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z() );
} }
} }
kpin->writeSpiceDriver( &modelData, modelName, *kmodel, kparams );
if( type == SIM_MODEL::TYPE::KIBIS_DIFFDRIVER )
kpin->writeSpiceDiffDriver( &modelData, modelName, *kmodel, kparams );
else
kpin->writeSpiceDriver( &modelData, modelName, *kmodel, kparams );
break; break;
} }
default: continue; default: continue;

View File

@ -30,7 +30,7 @@
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath ) void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath, SIM_MODEL::TYPE aType )
{ {
SIM_LIBRARY::ReadFile( aFilePath ); SIM_LIBRARY::ReadFile( aFilePath );
m_kibis = KIBIS( std::string( aFilePath.c_str() ) ); m_kibis = KIBIS( std::string( aFilePath.c_str() ) );
@ -41,13 +41,20 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
return; return;
} }
unsigned pinNumber = 2;
if( aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE || aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE )
pinNumber = 3;
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components ) for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
{ {
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, 2 ) ); m_models.push_back( SIM_MODEL::Create( aType, pinNumber ) );
m_modelNames.emplace_back( kcomp.m_name ); m_modelNames.emplace_back( kcomp.m_name );
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() ); SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
InitModel( *libcomp, kcomp.m_name );
if ( libcomp )
InitModel( *libcomp, kcomp.m_name );
} }
} }

View File

@ -37,7 +37,11 @@ public:
static constexpr auto MODEL_FIELD = "Ibis_Model"; static constexpr auto MODEL_FIELD = "Ibis_Model";
// @copydoc SIM_LIBRARY::ReadFile() // @copydoc SIM_LIBRARY::ReadFile()
void ReadFile( const std::string& aFilePath ) override; void ReadFile( const std::string& aFilePath, SIM_MODEL::TYPE aType );
void ReadFile( const std::string& aFilePath ) override
{
ReadFile( aFilePath, SIM_MODEL::TYPE::KIBIS_DEVICE );
}
// @copydoc SIM_LIBRARY::WriteFile() // @copydoc SIM_LIBRARY::WriteFile()
void WriteFile( const std::string& aFilePath ) override{}; void WriteFile( const std::string& aFilePath ) override{};

View File

@ -229,8 +229,10 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
//case TYPE::I_RANDPOISSON: return { DEVICE_TYPE::I, "RANDPOISSON", "Random Poisson" }; //case TYPE::I_RANDPOISSON: return { DEVICE_TYPE::I, "RANDPOISSON", "Random Poisson" };
case TYPE::I_BEHAVIORAL: return { DEVICE_TYPE_::I, "=", "Behavioral" }; case TYPE::I_BEHAVIORAL: return { DEVICE_TYPE_::I, "=", "Behavioral" };
case TYPE::KIBIS_DRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDRIVER", "Driver" }; case TYPE::KIBIS_DRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDRIVER", "Driver" };
case TYPE::KIBIS_DEVICE: return { DEVICE_TYPE_::KIBIS, "IBISDEVICE", "Device" }; case TYPE::KIBIS_DEVICE: return { DEVICE_TYPE_::KIBIS, "IBISDEVICE", "Device" };
case TYPE::KIBIS_DIFFDRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDIFFDRIVER", "Differential driver" };
case TYPE::KIBIS_DIFFDEVICE: return { DEVICE_TYPE_::KIBIS, "IBISDIFFDEVICE", "Differential device" };
case TYPE::SUBCKT: return { DEVICE_TYPE_::SUBCKT, "", "" }; case TYPE::SUBCKT: return { DEVICE_TYPE_::SUBCKT, "", "" };
case TYPE::XSPICE: return { DEVICE_TYPE_::XSPICE, "", "" }; case TYPE::XSPICE: return { DEVICE_TYPE_::XSPICE, "", "" };
case TYPE::RAWSPICE: return { DEVICE_TYPE_::SPICE, "", "" }; case TYPE::RAWSPICE: return { DEVICE_TYPE_::SPICE, "", "" };
@ -365,6 +367,9 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
case TYPE::KIBIS_DEVICE: return { "X" }; case TYPE::KIBIS_DEVICE: return { "X" };
case TYPE::KIBIS_DRIVER: return { "X" }; case TYPE::KIBIS_DRIVER: return { "X" };
case TYPE::KIBIS_DIFFDEVICE: return { "X" };
case TYPE::KIBIS_DIFFDRIVER: return { "X" };
case TYPE::NONE: case TYPE::NONE:
case TYPE::RAWSPICE: case TYPE::RAWSPICE:
return {}; return {};
@ -949,6 +954,8 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType )
case TYPE::KIBIS_DRIVER: case TYPE::KIBIS_DRIVER:
case TYPE::KIBIS_DEVICE: case TYPE::KIBIS_DEVICE:
case TYPE::KIBIS_DIFFDEVICE:
case TYPE::KIBIS_DIFFDRIVER:
return std::make_unique<SIM_MODEL_KIBIS>( aType ); return std::make_unique<SIM_MODEL_KIBIS>( aType );
case TYPE::RAWSPICE: case TYPE::RAWSPICE:

View File

@ -298,6 +298,8 @@ public:
KIBIS_DRIVER, KIBIS_DRIVER,
KIBIS_DEVICE, KIBIS_DEVICE,
KIBIS_DIFFDEVICE,
KIBIS_DIFFDRIVER,
SUBCKT, SUBCKT,
XSPICE, XSPICE,
@ -502,7 +504,7 @@ public:
DEVICE_TYPE_ GetDeviceType() const { return GetTypeInfo().deviceType; } DEVICE_TYPE_ GetDeviceType() const { return GetTypeInfo().deviceType; }
TYPE GetType() const { return m_type; } TYPE GetType() const { return m_type; }
const SIM_MODEL* GetBaseModel() const { return m_baseModel; } virtual const SIM_MODEL* GetBaseModel() const { return m_baseModel; }
virtual void SetBaseModel( const SIM_MODEL& aBaseModel ) { m_baseModel = &aBaseModel; } virtual void SetBaseModel( const SIM_MODEL& aBaseModel ) { m_baseModel = &aBaseModel; }
int GetPinCount() const { return static_cast<int>( m_pins.size() ); } int GetPinCount() const { return static_cast<int>( m_pins.size() ); }
@ -517,7 +519,7 @@ public:
int GetParamCount() const { return static_cast<int>( m_params.size() ); } int GetParamCount() const { return static_cast<int>( m_params.size() ); }
const PARAM& GetParam( unsigned aParamIndex ) const; // Return base parameter unless it's overridden. virtual const PARAM& GetParam( unsigned aParamIndex ) const; // Return base parameter unless it's overridden.
const PARAM* FindParam( const std::string& aParamName ) const; const PARAM* FindParam( const std::string& aParamName ) const;
@ -571,6 +573,7 @@ protected:
bool aAllowParamValuePairs = true ); bool aAllowParamValuePairs = true );
std::vector<PARAM> m_params; std::vector<PARAM> m_params;
bool m_requiresUIUpdate = false; bool m_requiresUIUpdate = false;
const SIM_MODEL* m_baseModel;
private: private:
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString, static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
@ -599,7 +602,6 @@ private:
std::unique_ptr<SPICE_GENERATOR> m_spiceGenerator; std::unique_ptr<SPICE_GENERATOR> m_spiceGenerator;
const SIM_MODEL* m_baseModel;
const TYPE m_type; const TYPE m_type;
std::vector<PIN> m_pins; std::vector<PIN> m_pins;

View File

@ -59,16 +59,25 @@ SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, std::string aWfType ) :
{ {
SetParameters( aType, aWfType ); SetParameters( aType, aWfType );
AddPin( { "GND", "1" } ); if( aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE || aType == SIM_MODEL::TYPE::KIBIS_DIFFDRIVER )
AddPin( { "IN/OUT", "2" } ); {
AddPin( { "GND", "1" } );
AddPin( { "+", "2" } );
AddPin( { "-", "3" } );
}
else
{
AddPin( { "GND", "1" } );
AddPin( { "IN/OUT", "2" } );
}
} }
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource ) : SIM_MODEL_KIBIS( aType ) SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) : SIM_MODEL_KIBIS( aType )
{ {
for( PARAM& param1 : m_params ) for( PARAM& param1 : m_params )
{ {
for( auto param2refwrap : aSource.GetParams() ) for( auto& param2refwrap : aSource.GetParams() )
{ {
const PARAM& param2 = param2refwrap.get(); const PARAM& param2 = param2refwrap.get();
@ -109,8 +118,10 @@ void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_STUCKL ); makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_STUCKL );
static std::vector<PARAM::INFO> kibisparam_driver_highz = static std::vector<PARAM::INFO> kibisparam_driver_highz =
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_HIGHZ ); makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_HIGHZ );
static std::vector<PARAM::INFO> kibisparam_driver_prbs =
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_PRBS );
static std::vector<PARAM::INFO> kibisparam_driver_allParams = static std::vector<PARAM::INFO> kibisparam_driver_allParams =
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, "NoInit" ); makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::JOCKER );
m_requiresUIUpdate = true; m_requiresUIUpdate = true;
@ -118,7 +129,9 @@ void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
switch( aType ) switch( aType )
{ {
case SIM_MODEL::TYPE::KIBIS_DEVICE: params = &kibisparam_device; break; case SIM_MODEL::TYPE::KIBIS_DEVICE:
case SIM_MODEL::TYPE::KIBIS_DIFFDEVICE: params = &kibisparam_device; break;
case SIM_MODEL::TYPE::KIBIS_DIFFDRIVER:
case SIM_MODEL::TYPE::KIBIS_DRIVER: case SIM_MODEL::TYPE::KIBIS_DRIVER:
if( aWfType == SIM_MODEL_KIBIS::DRIVER_RECT ) if( aWfType == SIM_MODEL_KIBIS::DRIVER_RECT )
@ -129,6 +142,8 @@ void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
params = &kibisparam_driver_stuckl; params = &kibisparam_driver_stuckl;
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_HIGHZ ) else if( aWfType == SIM_MODEL_KIBIS::DRIVER_HIGHZ )
params = &kibisparam_driver_highz; params = &kibisparam_driver_highz;
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_PRBS )
params = &kibisparam_driver_prbs;
else else
params = &kibisparam_driver_allParams; params = &kibisparam_driver_allParams;
// All params allow for a newly created model to read any parameter // All params allow for a newly created model to read any parameter
@ -137,6 +152,9 @@ void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
default: wxFAIL; return; default: wxFAIL; return;
} }
m_params.clear();
/*
if( m_params.empty() ) if( m_params.empty() )
{ {
for( const PARAM::INFO& paramInfo : *params ) for( const PARAM::INFO& paramInfo : *params )
@ -151,14 +169,10 @@ void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
m_params.pop_back(); // waveform parameters are at the end of the vector m_params.pop_back(); // waveform parameters are at the end of the vector
} }
} }
*/
for( const PARAM::INFO& paramInfo : *params ) for( const PARAM::INFO& paramInfo : *params )
{ AddParam( paramInfo );
if( paramInfo.category == PARAM::CATEGORY::WAVEFORM )
{
AddParam( paramInfo );
}
}
} }
void SIM_MODEL_KIBIS::SetParameters( std::string aWfType ) void SIM_MODEL_KIBIS::SetParameters( std::string aWfType )
@ -204,7 +218,7 @@ SIM_MODEL_KIBIS::makeKibisParamInfos( TYPE aType, std::string aWfType )
paramInfos.push_back( paramInfo ); paramInfos.push_back( paramInfo );
paramInfo.name = "lpin"; paramInfo.name = "lpin";
paramInfo.type = SIM_VALUE::TYPE_STRING; paramInfo.type = SIM_VALUE::TYPE_STRING;
paramInfo.unit = ""; paramInfo.unit = "";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL; paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "TYP"; paramInfo.defaultValue = "TYP";
@ -223,9 +237,26 @@ SIM_MODEL_KIBIS::makeKibisParamInfos( TYPE aType, std::string aWfType )
paramInfo.enumValues = { "TYP", "MIN", "MAX" }; paramInfo.enumValues = { "TYP", "MIN", "MAX" };
paramInfos.push_back( paramInfo ); paramInfos.push_back( paramInfo );
if ( aType == SIM_MODEL::TYPE::KIBIS_DEVICE ) if( aType == SIM_MODEL::TYPE::KIBIS_DEVICE || aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE )
return paramInfos; // Devices have no waveform parameters return paramInfos; // Devices have no waveform parameters
paramInfo.name = "wftype";
paramInfo.type = SIM_VALUE::TYPE_STRING;
paramInfo.unit = "";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = DRIVER_HIGHZ;
paramInfo.description = _( "Waveform" );
paramInfo.spiceModelName = "";
paramInfo.enumValues = { DRIVER_RECT, DRIVER_STUCKH, DRIVER_STUCKL, DRIVER_HIGHZ, DRIVER_PRBS };
paramInfos.push_back( paramInfo );
if( aWfType == DRIVER_STUCKH || aWfType == DRIVER_STUCKL || aWfType == DRIVER_HIGHZ )
{
return paramInfos;
}
paramInfo.name = "ac"; paramInfo.name = "ac";
paramInfo.type = SIM_VALUE::TYPE_STRING; paramInfo.type = SIM_VALUE::TYPE_STRING;
paramInfo.unit = ""; paramInfo.unit = "";
@ -236,47 +267,58 @@ SIM_MODEL_KIBIS::makeKibisParamInfos( TYPE aType, std::string aWfType )
paramInfo.enumValues = { "low", "normal", "high" }; paramInfo.enumValues = { "low", "normal", "high" };
paramInfos.push_back( paramInfo ); paramInfos.push_back( paramInfo );
paramInfo.name = "wftype"; if ( aWfType == DRIVER_RECT || aWfType == JOCKER )
paramInfo.type = SIM_VALUE::TYPE_STRING;
paramInfo.unit = "";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = DRIVER_HIGHZ;
paramInfo.description = _( "Waveform" );
paramInfo.spiceModelName = "";
paramInfo.enumValues = { DRIVER_RECT, DRIVER_STUCKH, DRIVER_STUCKL, DRIVER_HIGHZ };
paramInfos.push_back( paramInfo );
if( aWfType == DRIVER_STUCKH || aWfType == DRIVER_STUCKL || aWfType == DRIVER_HIGHZ )
{ {
return paramInfos; paramInfo.name = "ton";
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = "";
paramInfo.description = _( "ON time" );
paramInfo.spiceModelName = "";
paramInfos.push_back( paramInfo );
paramInfo.name = "toff";
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = "";
paramInfo.description = _( "OFF time" );
paramInfo.spiceModelName = "";
paramInfos.push_back( paramInfo );
paramInfo.name = "delay";
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = "0";
paramInfo.description = _( "Delay" );
paramInfo.spiceModelName = "";
paramInfos.push_back( paramInfo );
} }
paramInfo.name = "ton"; if ( ( aWfType == DRIVER_PRBS ) || ( aWfType == JOCKER ) )
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = "";
paramInfo.description = _( "ON time" );
paramInfo.spiceModelName = "";
paramInfos.push_back( paramInfo );
paramInfo.name = "toff"; {
paramInfo.type = SIM_VALUE::TYPE_FLOAT; paramInfo.name = "f0";
paramInfo.unit = "s"; paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.category = PARAM::CATEGORY::WAVEFORM; paramInfo.unit = "Hz";
paramInfo.defaultValue = ""; paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.description = _( "OFF time" ); paramInfo.defaultValue = "";
paramInfo.spiceModelName = ""; paramInfo.description = _( "Bitrate" );
paramInfos.push_back( paramInfo ); paramInfo.spiceModelName = "";
paramInfos.push_back( paramInfo );
paramInfo.name = "delay"; paramInfo.name = "bits";
paramInfo.type = SIM_VALUE::TYPE_FLOAT; paramInfo.type = SIM_VALUE::TYPE_FLOAT;
paramInfo.unit = "s"; paramInfo.unit = "Hz";
paramInfo.category = PARAM::CATEGORY::WAVEFORM; paramInfo.category = PARAM::CATEGORY::WAVEFORM;
paramInfo.defaultValue = "0"; paramInfo.defaultValue = "";
paramInfo.description = _( "Delay" ); paramInfo.description = _( "Number of bits" );
paramInfo.spiceModelName = ""; paramInfo.spiceModelName = "";
paramInfos.push_back( paramInfo ); paramInfos.push_back( paramInfo );
}
return paramInfos; return paramInfos;
} }

View File

@ -50,13 +50,15 @@ class SIM_MODEL_KIBIS : public SIM_MODEL
static constexpr auto DRIVER_STUCKH = "stuck high"; static constexpr auto DRIVER_STUCKH = "stuck high";
static constexpr auto DRIVER_STUCKL = "stuck low"; static constexpr auto DRIVER_STUCKL = "stuck low";
static constexpr auto DRIVER_HIGHZ = "high Z"; static constexpr auto DRIVER_HIGHZ = "high Z";
static constexpr auto DRIVER_PRBS = "prbs";
static constexpr auto JOCKER = "kicadjocker"; // Gets all parameters
public: public:
SIM_MODEL_KIBIS( TYPE aType, std::string aWfType = "NoInit" ); SIM_MODEL_KIBIS( TYPE aType, std::string aWfType = "NoInit" );
// @brief Special copy constructor // @brief Special copy constructor
// creates a a model with aType, but tries to match parameters from aSource. // creates a a model with aType, but tries to match parameters from aSource.
SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource ); SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource );
SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector<LIB_FIELD>& aFields ); SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector<LIB_FIELD>& aFields );
SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector<SCH_FIELD>& aFields ); SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector<SCH_FIELD>& aFields );
@ -80,6 +82,9 @@ public:
: m_componentName; : m_componentName;
}; };
const PARAM& GetParam( unsigned aParamIndex ) const override { return m_params.at( aParamIndex ); };
/** @brief update the list of available models based on the pin number. /** @brief update the list of available models based on the pin number.
* */ * */
bool ChangePin( SIM_LIBRARY_KIBIS& aLib, std::string aPinNumber ); bool ChangePin( SIM_LIBRARY_KIBIS& aLib, std::string aPinNumber );

View File

@ -481,6 +481,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
{ {
IBIS_CORNER supply = aParam.m_supply; IBIS_CORNER supply = aParam.m_supply;
std::string simul; std::string simul;
std::vector<int>stimuliIndex;
IbisWaveform risingWF = TrimWaveform( *( aPair.first ) ); IbisWaveform risingWF = TrimWaveform( *( aPair.first ) );
IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) ); IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) );
@ -495,16 +496,24 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
double delta = deltaR + deltaF; double delta = deltaR + deltaF;
int i = 0; int i = 0;
int prevBit = 2;
for( std::pair<int, double> bit : aBits ) for( std::pair<int, double> bit : aBits )
{ {
IbisWaveform* WF; IbisWaveform* WF;
double timing = bit.second; double timing = bit.second;
if ( bit.first != prevBit )
{
if( bit.first == 1 ) if( bit.first == 1 )
WF = &risingWF; WF = &risingWF;
else else
WF = &fallingWF; WF = &fallingWF;
stimuliIndex.push_back( i );
simul += "Vstimuli"; simul += "Vstimuli";
simul += std::to_string( i ); simul += std::to_string( i );
simul += " stimuli"; simul += " stimuli";
@ -534,8 +543,10 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
simul += " "; simul += " ";
} }
simul += ")\n"; simul += ")\n";
}
i++; i++;
prevBit = bit.first;
} }
simul += "bin "; simul += "bin ";
@ -544,7 +555,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
simul += aNode2; simul += aNode2;
simul += " v=("; simul += " v=(";
for( size_t ii = 0; ii < aBits.size(); ii++ ) for( int ii: stimuliIndex )
{ {
simul += " v( stimuli"; simul += " v( stimuli";
simul += std::to_string( ii ); simul += std::to_string( ii );
@ -797,6 +808,13 @@ std::string KIBIS_PIN::KuKdDriver( KIBIS_MODEL& aMode
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam ); simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
break; break;
} }
case KIBIS_WAVEFORM_TYPE::PRBS:
{
KIBIS_WAVEFORM_PRBS* prbsWave = dynamic_cast<KIBIS_WAVEFORM_PRBS*>( wave );
std::vector<std::pair<int, double>> bits = prbsWave->GenerateBitSequence();
simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
break;
}
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH: case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
{ {
IbisWaveform* waveform = wave->inverted ? risingWF : fallingWF; IbisWaveform* waveform = wave->inverted ? risingWF : fallingWF;
@ -901,8 +919,15 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
switch( wave->GetType() ) switch( wave->GetType() )
{ {
case KIBIS_WAVEFORM_TYPE::RECTANGULAR: simul += ".tran 0.1n 1000n \n"; break; case KIBIS_WAVEFORM_TYPE::PRBS:
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
{
double duration = wave->GetDuration();
simul += ".tran 0.1n ";
simul += doubleToString( duration );
simul += "\n";
break;
}
case KIBIS_WAVEFORM_TYPE::HIGH_Z: case KIBIS_WAVEFORM_TYPE::HIGH_Z:
case KIBIS_WAVEFORM_TYPE::STUCK_LOW: case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH: case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
@ -1097,15 +1122,30 @@ void KIBIS_PIN::getKuKdTwoWaveforms( KIBIS_MODEL& aMo
Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR ); Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
} }
simul += ".tran 0.1n 1000n \n"; switch( wave->GetType() )
{
case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
case KIBIS_WAVEFORM_TYPE::PRBS:
{
double duration = wave->GetDuration();
simul += ".tran 0.1n ";
simul += doubleToString( duration );
simul += "\n";
break;
}
case KIBIS_WAVEFORM_TYPE::HIGH_Z:
case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
default: simul += ".tran 0.5 1 \n"; //
}
//simul += ".dc Vpin -5 5 0.1\n"; //simul += ".dc Vpin -5 5 0.1\n";
simul += ".control run \n"; simul += ".control run \n";
simul += "set filetype=ascii\n"; simul += "set filetype=ascii\n";
simul += "run \n"; simul += "run \n";
simul += "plot v(KU) v(KD)\n"; simul += "plot v(KU) v(KD)\n";
simul += "plot v(x1.DIE0) \n"; //simul += "plot v(x1.DIE0) \n";
simul += "write temp_output.spice v(KU) v(KD)\n"; // @TODO we might want to remove this... simul += "write temp_output.spice v(KU) v(KD)\n"; // @TODO we might want to remove this...
//simul += "quit\n"; simul += "quit\n";
simul += ".endc \n"; simul += ".endc \n";
simul += ".end \n"; simul += ".end \n";
@ -1142,13 +1182,13 @@ bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_M
if( m_parent ) if( m_parent )
{ {
result += m_parent->m_name; //result += m_parent->m_name;
} }
result += "\n*Manufacturer: "; result += "\n*Manufacturer: ";
if( m_parent ) if( m_parent )
{ {
result += m_parent->m_manufacturer; //result += m_parent->m_manufacturer;
} }
result += "\n*Pin number: "; result += "\n*Pin number: ";
result += m_pinNumber; result += m_pinNumber;
@ -1303,13 +1343,13 @@ bool KIBIS_PIN::writeSpiceDiffDriver( std::string* aDest, std::string aName, KIB
if( m_parent ) if( m_parent )
{ {
result += m_parent->m_name; //result += m_parent->m_name;
} }
result += "\n*Manufacturer: "; result += "\n*Manufacturer: ";
if( m_parent ) if( m_parent )
{ {
result += m_parent->m_manufacturer; //result += m_parent->m_manufacturer;
} }
result += "\n.SUBCKT "; result += "\n.SUBCKT ";
@ -1350,13 +1390,13 @@ bool KIBIS_PIN::writeSpiceDiffDevice( std::string* aDest, std::string aName, KIB
if( m_parent ) if( m_parent )
{ {
result += m_parent->m_name; //result += m_parent->m_name;
} }
result += "\n*Manufacturer: "; result += "\n*Manufacturer: ";
if( m_parent ) if( m_parent )
{ {
result += m_parent->m_manufacturer; //result += m_parent->m_manufacturer;
} }
result += "\n.SUBCKT "; result += "\n.SUBCKT ";
@ -1414,3 +1454,38 @@ void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, std::string aSt
else else
aCorner = IBIS_CORNER::TYP; aCorner = IBIS_CORNER::TYP;
} }
std::vector<std::pair<int, double>> KIBIS_WAVEFORM_PRBS::GenerateBitSequence()
{
std::vector<std::pair<int, double>> bitSequence;
uint8_t polynomial = 0b1100000;
//1100000 = x^7+x^6+1
//10100 = x^5+x^3+1
//110 = x^3+x^2+1
uint8_t seed = 0x12; // Any non zero state
uint8_t lfsr = seed;
if ( m_bitrate == 0 )
return bitSequence;
double period = 1/m_bitrate;
double t = 0;
m_bits = abs( m_bits ); // Just to be sure.
int bits = 0;
do
{
uint8_t lsb = lfsr & 0x01;
bitSequence.emplace_back( ( inverted ^ lsb ? 1 : 0 ), t );
lfsr = lfsr >> 1;
if ( lsb )
lfsr ^= polynomial;
t += period;
} while ( ++bits < m_bits );
return bitSequence;
}

View File

@ -51,6 +51,7 @@ public:
enum KIBIS_WAVEFORM_TYPE enum KIBIS_WAVEFORM_TYPE
{ {
NONE = 0, // Used for three state NONE = 0, // Used for three state
PRBS,
RECTANGULAR, RECTANGULAR,
STUCK_HIGH, STUCK_HIGH,
STUCK_LOW, STUCK_LOW,
@ -63,6 +64,7 @@ class KIBIS_WAVEFORM
public: public:
KIBIS_WAVEFORM(){}; KIBIS_WAVEFORM(){};
KIBIS_WAVEFORM_TYPE GetType() { return m_type; }; KIBIS_WAVEFORM_TYPE GetType() { return m_type; };
virtual double GetDuration() { return 1; };
bool inverted = false; // Used for differential drivers bool inverted = false; // Used for differential drivers
virtual ~KIBIS_WAVEFORM(){}; virtual ~KIBIS_WAVEFORM(){};
@ -76,8 +78,23 @@ public:
KIBIS_WAVEFORM_RECTANGULAR() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR; }; KIBIS_WAVEFORM_RECTANGULAR() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR; };
double m_ton = 100e-9; double m_ton = 100e-9;
double m_toff = 100e-9; double m_toff = 100e-9;
int m_cycles = 10; int m_cycles = 1;
double m_delay = 0; double m_delay = 0;
double GetDuration() override { return ( m_ton + m_toff ) * m_cycles; };
};
// For now, we only support PRBS7
class KIBIS_WAVEFORM_PRBS : public KIBIS_WAVEFORM
{
public:
KIBIS_WAVEFORM_PRBS() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::PRBS; };
double m_bitrate = 10e6;
double m_delay = 0;
double m_bits = 10;
std::vector<std::pair<int, double>> GenerateBitSequence();
double GetDuration() override { return m_bits / m_bitrate ; };
}; };
class KIBIS_WAVEFORM_STUCK_HIGH : public KIBIS_WAVEFORM class KIBIS_WAVEFORM_STUCK_HIGH : public KIBIS_WAVEFORM

View File

@ -43,6 +43,8 @@ int main( void )
KIBIS_PARAMETER params; KIBIS_PARAMETER params;
params.m_waveform = new KIBIS_WAVEFORM_RECTANGULAR();
pin2->writeSpiceDevice( tmp4, "device_typ", *( pin2->m_models.at( 0 ) ), params ); pin2->writeSpiceDevice( tmp4, "device_typ", *( pin2->m_models.at( 0 ) ), params );
KIBIS_MODEL* model1 = pin1->m_models.at( 0 ); KIBIS_MODEL* model1 = pin1->m_models.at( 0 );