Ibis differential and PRBS models
This commit is contained in:
parent
8ae48bb093
commit
7e486327d9
|
@ -524,7 +524,26 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
|
|||
|
||||
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 )
|
||||
{
|
||||
|
@ -1010,8 +1029,9 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
|
|||
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
|
||||
{
|
||||
if( IsIbisLoaded()
|
||||
&& ( type == SIM_MODEL::TYPE::KIBIS_DEVICE
|
||||
|| type == SIM_MODEL::TYPE::KIBIS_DRIVER ) )
|
||||
&& ( type == SIM_MODEL::TYPE::KIBIS_DEVICE || 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::dynamic_pointer_cast<SIM_MODEL_KIBIS>(
|
||||
|
|
|
@ -273,6 +273,8 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
|
||||
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_DRIVER: break;
|
||||
default:
|
||||
|
@ -329,6 +331,10 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
case SIM_MODEL::TYPE::KIBIS_DEVICE:
|
||||
kpin->writeSpiceDevice( &modelData, modelName, *kmodel, kparams );
|
||||
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:
|
||||
{
|
||||
mparam = spiceItem.model->FindParam( "wftype" );
|
||||
|
@ -369,6 +375,39 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
->Get()
|
||||
.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" )
|
||||
{
|
||||
kparams.m_waveform =
|
||||
|
@ -385,7 +424,11 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
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;
|
||||
}
|
||||
default: continue;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#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 );
|
||||
m_kibis = KIBIS( std::string( aFilePath.c_str() ) );
|
||||
|
@ -41,13 +41,20 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath )
|
|||
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 )
|
||||
{
|
||||
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 );
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,11 @@ public:
|
|||
static constexpr auto MODEL_FIELD = "Ibis_Model";
|
||||
|
||||
// @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()
|
||||
void WriteFile( const std::string& aFilePath ) override{};
|
||||
|
|
|
@ -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_BEHAVIORAL: return { DEVICE_TYPE_::I, "=", "Behavioral" };
|
||||
|
||||
case TYPE::KIBIS_DRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDRIVER", "Driver" };
|
||||
case TYPE::KIBIS_DEVICE: return { DEVICE_TYPE_::KIBIS, "IBISDEVICE", "Device" };
|
||||
case TYPE::KIBIS_DRIVER: return { DEVICE_TYPE_::KIBIS, "IBISDRIVER", "Driver" };
|
||||
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::XSPICE: return { DEVICE_TYPE_::XSPICE, "", "" };
|
||||
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_DRIVER: return { "X" };
|
||||
case TYPE::KIBIS_DIFFDEVICE: return { "X" };
|
||||
case TYPE::KIBIS_DIFFDRIVER: return { "X" };
|
||||
|
||||
case TYPE::NONE:
|
||||
case TYPE::RAWSPICE:
|
||||
return {};
|
||||
|
@ -949,6 +954,8 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType )
|
|||
|
||||
case TYPE::KIBIS_DRIVER:
|
||||
case TYPE::KIBIS_DEVICE:
|
||||
case TYPE::KIBIS_DIFFDEVICE:
|
||||
case TYPE::KIBIS_DIFFDRIVER:
|
||||
return std::make_unique<SIM_MODEL_KIBIS>( aType );
|
||||
|
||||
case TYPE::RAWSPICE:
|
||||
|
|
|
@ -298,6 +298,8 @@ public:
|
|||
|
||||
KIBIS_DRIVER,
|
||||
KIBIS_DEVICE,
|
||||
KIBIS_DIFFDEVICE,
|
||||
KIBIS_DIFFDRIVER,
|
||||
|
||||
SUBCKT,
|
||||
XSPICE,
|
||||
|
@ -502,7 +504,7 @@ public:
|
|||
DEVICE_TYPE_ GetDeviceType() const { return GetTypeInfo().deviceType; }
|
||||
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; }
|
||||
|
||||
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() ); }
|
||||
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;
|
||||
|
||||
|
@ -571,6 +573,7 @@ protected:
|
|||
bool aAllowParamValuePairs = true );
|
||||
std::vector<PARAM> m_params;
|
||||
bool m_requiresUIUpdate = false;
|
||||
const SIM_MODEL* m_baseModel;
|
||||
|
||||
private:
|
||||
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
|
||||
|
@ -599,7 +602,6 @@ private:
|
|||
|
||||
|
||||
std::unique_ptr<SPICE_GENERATOR> m_spiceGenerator;
|
||||
const SIM_MODEL* m_baseModel;
|
||||
|
||||
const TYPE m_type;
|
||||
std::vector<PIN> m_pins;
|
||||
|
|
|
@ -59,16 +59,25 @@ SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, std::string aWfType ) :
|
|||
{
|
||||
SetParameters( aType, aWfType );
|
||||
|
||||
AddPin( { "GND", "1" } );
|
||||
AddPin( { "IN/OUT", "2" } );
|
||||
if( aType == SIM_MODEL::TYPE::KIBIS_DIFFDEVICE || aType == SIM_MODEL::TYPE::KIBIS_DIFFDRIVER )
|
||||
{
|
||||
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( auto param2refwrap : aSource.GetParams() )
|
||||
for( auto& param2refwrap : aSource.GetParams() )
|
||||
{
|
||||
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 );
|
||||
static std::vector<PARAM::INFO> kibisparam_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 =
|
||||
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, "NoInit" );
|
||||
makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::JOCKER );
|
||||
|
||||
m_requiresUIUpdate = true;
|
||||
|
||||
|
@ -118,7 +129,9 @@ void SIM_MODEL_KIBIS::SetParameters( TYPE aType, std::string aWfType )
|
|||
|
||||
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:
|
||||
|
||||
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;
|
||||
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_HIGHZ )
|
||||
params = &kibisparam_driver_highz;
|
||||
else if( aWfType == SIM_MODEL_KIBIS::DRIVER_PRBS )
|
||||
params = &kibisparam_driver_prbs;
|
||||
else
|
||||
params = &kibisparam_driver_allParams;
|
||||
// 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;
|
||||
}
|
||||
|
||||
m_params.clear();
|
||||
|
||||
/*
|
||||
if( m_params.empty() )
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for( const PARAM::INFO& paramInfo : *params )
|
||||
{
|
||||
if( paramInfo.category == PARAM::CATEGORY::WAVEFORM )
|
||||
{
|
||||
AddParam( paramInfo );
|
||||
}
|
||||
}
|
||||
AddParam( paramInfo );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
paramInfo.name = "lpin";
|
||||
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||
paramInfo.type = SIM_VALUE::TYPE_STRING;
|
||||
paramInfo.unit = "";
|
||||
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "TYP";
|
||||
|
@ -223,9 +237,26 @@ SIM_MODEL_KIBIS::makeKibisParamInfos( TYPE aType, std::string aWfType )
|
|||
paramInfo.enumValues = { "TYP", "MIN", "MAX" };
|
||||
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
|
||||
|
||||
|
||||
|
||||
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.type = SIM_VALUE::TYPE_STRING;
|
||||
paramInfo.unit = "";
|
||||
|
@ -236,47 +267,58 @@ SIM_MODEL_KIBIS::makeKibisParamInfos( TYPE aType, std::string aWfType )
|
|||
paramInfo.enumValues = { "low", "normal", "high" };
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
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 };
|
||||
paramInfos.push_back( paramInfo );
|
||||
if ( aWfType == DRIVER_RECT || aWfType == JOCKER )
|
||||
|
||||
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";
|
||||
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 );
|
||||
if ( ( aWfType == DRIVER_PRBS ) || ( aWfType == JOCKER ) )
|
||||
|
||||
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 = "f0";
|
||||
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
|
||||
paramInfo.unit = "Hz";
|
||||
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||
paramInfo.defaultValue = "";
|
||||
paramInfo.description = _( "Bitrate" );
|
||||
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 = "bits";
|
||||
paramInfo.type = SIM_VALUE::TYPE_FLOAT;
|
||||
paramInfo.unit = "Hz";
|
||||
paramInfo.category = PARAM::CATEGORY::WAVEFORM;
|
||||
paramInfo.defaultValue = "";
|
||||
paramInfo.description = _( "Number of bits" );
|
||||
paramInfo.spiceModelName = "";
|
||||
paramInfos.push_back( paramInfo );
|
||||
}
|
||||
|
||||
return paramInfos;
|
||||
}
|
||||
|
|
|
@ -50,13 +50,15 @@ class SIM_MODEL_KIBIS : public SIM_MODEL
|
|||
static constexpr auto DRIVER_STUCKH = "stuck high";
|
||||
static constexpr auto DRIVER_STUCKL = "stuck low";
|
||||
static constexpr auto DRIVER_HIGHZ = "high Z";
|
||||
static constexpr auto DRIVER_PRBS = "prbs";
|
||||
static constexpr auto JOCKER = "kicadjocker"; // Gets all parameters
|
||||
|
||||
public:
|
||||
SIM_MODEL_KIBIS( TYPE aType, std::string aWfType = "NoInit" );
|
||||
|
||||
// @brief Special copy constructor
|
||||
// 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<SCH_FIELD>& aFields );
|
||||
|
@ -80,6 +82,9 @@ public:
|
|||
: 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.
|
||||
* */
|
||||
bool ChangePin( SIM_LIBRARY_KIBIS& aLib, std::string aPinNumber );
|
||||
|
|
|
@ -481,6 +481,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
|
|||
{
|
||||
IBIS_CORNER supply = aParam.m_supply;
|
||||
std::string simul;
|
||||
std::vector<int>stimuliIndex;
|
||||
|
||||
IbisWaveform risingWF = TrimWaveform( *( aPair.first ) );
|
||||
IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) );
|
||||
|
@ -495,16 +496,24 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
|
|||
double delta = deltaR + deltaF;
|
||||
|
||||
int i = 0;
|
||||
|
||||
int prevBit = 2;
|
||||
|
||||
for( std::pair<int, double> bit : aBits )
|
||||
{
|
||||
IbisWaveform* WF;
|
||||
double timing = bit.second;
|
||||
|
||||
|
||||
if ( bit.first != prevBit )
|
||||
{
|
||||
if( bit.first == 1 )
|
||||
WF = &risingWF;
|
||||
else
|
||||
WF = &fallingWF;
|
||||
|
||||
stimuliIndex.push_back( i );
|
||||
|
||||
simul += "Vstimuli";
|
||||
simul += std::to_string( i );
|
||||
simul += " stimuli";
|
||||
|
@ -534,8 +543,10 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
|
|||
simul += " ";
|
||||
}
|
||||
simul += ")\n";
|
||||
}
|
||||
|
||||
i++;
|
||||
prevBit = bit.first;
|
||||
}
|
||||
|
||||
simul += "bin ";
|
||||
|
@ -544,7 +555,7 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo
|
|||
simul += aNode2;
|
||||
simul += " v=(";
|
||||
|
||||
for( size_t ii = 0; ii < aBits.size(); ii++ )
|
||||
for( int ii: stimuliIndex )
|
||||
{
|
||||
simul += " v( stimuli";
|
||||
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 );
|
||||
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:
|
||||
{
|
||||
IbisWaveform* waveform = wave->inverted ? risingWF : fallingWF;
|
||||
|
@ -901,8 +919,15 @@ void KIBIS_PIN::getKuKdOneWaveform( KIBIS_MODEL& aMod
|
|||
|
||||
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::STUCK_LOW:
|
||||
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 );
|
||||
}
|
||||
|
||||
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 += ".control run \n";
|
||||
simul += "set filetype=ascii\n";
|
||||
simul += "run \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 += "quit\n";
|
||||
simul += "quit\n";
|
||||
simul += ".endc \n";
|
||||
simul += ".end \n";
|
||||
|
||||
|
@ -1142,13 +1182,13 @@ bool KIBIS_PIN::writeSpiceDriver( std::string* aDest, std::string aName, KIBIS_M
|
|||
|
||||
if( m_parent )
|
||||
{
|
||||
result += m_parent->m_name;
|
||||
//result += m_parent->m_name;
|
||||
}
|
||||
result += "\n*Manufacturer: ";
|
||||
|
||||
if( m_parent )
|
||||
{
|
||||
result += m_parent->m_manufacturer;
|
||||
//result += m_parent->m_manufacturer;
|
||||
}
|
||||
result += "\n*Pin number: ";
|
||||
result += m_pinNumber;
|
||||
|
@ -1303,13 +1343,13 @@ bool KIBIS_PIN::writeSpiceDiffDriver( std::string* aDest, std::string aName, KIB
|
|||
|
||||
if( m_parent )
|
||||
{
|
||||
result += m_parent->m_name;
|
||||
//result += m_parent->m_name;
|
||||
}
|
||||
result += "\n*Manufacturer: ";
|
||||
|
||||
if( m_parent )
|
||||
{
|
||||
result += m_parent->m_manufacturer;
|
||||
//result += m_parent->m_manufacturer;
|
||||
}
|
||||
|
||||
result += "\n.SUBCKT ";
|
||||
|
@ -1350,13 +1390,13 @@ bool KIBIS_PIN::writeSpiceDiffDevice( std::string* aDest, std::string aName, KIB
|
|||
|
||||
if( m_parent )
|
||||
{
|
||||
result += m_parent->m_name;
|
||||
//result += m_parent->m_name;
|
||||
}
|
||||
result += "\n*Manufacturer: ";
|
||||
|
||||
if( m_parent )
|
||||
{
|
||||
result += m_parent->m_manufacturer;
|
||||
//result += m_parent->m_manufacturer;
|
||||
}
|
||||
|
||||
result += "\n.SUBCKT ";
|
||||
|
@ -1414,3 +1454,38 @@ void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, std::string aSt
|
|||
else
|
||||
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;
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
enum KIBIS_WAVEFORM_TYPE
|
||||
{
|
||||
NONE = 0, // Used for three state
|
||||
PRBS,
|
||||
RECTANGULAR,
|
||||
STUCK_HIGH,
|
||||
STUCK_LOW,
|
||||
|
@ -63,6 +64,7 @@ class KIBIS_WAVEFORM
|
|||
public:
|
||||
KIBIS_WAVEFORM(){};
|
||||
KIBIS_WAVEFORM_TYPE GetType() { return m_type; };
|
||||
virtual double GetDuration() { return 1; };
|
||||
bool inverted = false; // Used for differential drivers
|
||||
virtual ~KIBIS_WAVEFORM(){};
|
||||
|
||||
|
@ -76,8 +78,23 @@ public:
|
|||
KIBIS_WAVEFORM_RECTANGULAR() : KIBIS_WAVEFORM() { m_type = KIBIS_WAVEFORM_TYPE::RECTANGULAR; };
|
||||
double m_ton = 100e-9;
|
||||
double m_toff = 100e-9;
|
||||
int m_cycles = 10;
|
||||
int m_cycles = 1;
|
||||
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
|
||||
|
|
|
@ -43,6 +43,8 @@ int main( void )
|
|||
|
||||
KIBIS_PARAMETER params;
|
||||
|
||||
params.m_waveform = new KIBIS_WAVEFORM_RECTANGULAR();
|
||||
|
||||
pin2->writeSpiceDevice( tmp4, "device_typ", *( pin2->m_models.at( 0 ) ), params );
|
||||
|
||||
KIBIS_MODEL* model1 = pin1->m_models.at( 0 );
|
||||
|
|
Loading…
Reference in New Issue