diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 2988baf309..403cc3ca5c 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -524,7 +524,26 @@ void DIALOG_SIM_MODEL::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( 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::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 kibismodel = std::dynamic_pointer_cast( diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 99afb05cc9..a0ecc379a5 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -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( + new KIBIS_WAVEFORM_PRBS() ); + + mparam = spiceItem.model->FindParam( "bitrate" ); + + if( mparam ) + static_cast( kparams.m_waveform ) + ->m_bitrate = static_cast( + std::dynamic_pointer_cast( mparam->value ) + ->Get() + .value_or( 1 ) ); + + mparam = spiceItem.model->FindParam( "nbits" ); + + if( mparam ) + static_cast( kparams.m_waveform ) + ->m_bits = static_cast( + std::dynamic_pointer_cast( mparam->value ) + ->Get() + .value_or( 1 ) ); + + mparam = spiceItem.model->FindParam( "delay" ); + + if( mparam ) + static_cast( kparams.m_waveform ) + ->m_delay = static_cast( + std::dynamic_pointer_cast( 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( 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; diff --git a/eeschema/sim/sim_library_kibis.cpp b/eeschema/sim/sim_library_kibis.cpp index 5dbd74cfd2..512cb3b6d5 100644 --- a/eeschema/sim/sim_library_kibis.cpp +++ b/eeschema/sim/sim_library_kibis.cpp @@ -30,7 +30,7 @@ #include -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( m_models.back().get() ); - InitModel( *libcomp, kcomp.m_name ); + + if ( libcomp ) + InitModel( *libcomp, kcomp.m_name ); } } diff --git a/eeschema/sim/sim_library_kibis.h b/eeschema/sim/sim_library_kibis.h index 6eff0c8beb..034966f598 100644 --- a/eeschema/sim/sim_library_kibis.h +++ b/eeschema/sim/sim_library_kibis.h @@ -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{}; diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index f4b10938b2..291702c7a2 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -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::Create( TYPE aType ) case TYPE::KIBIS_DRIVER: case TYPE::KIBIS_DEVICE: + case TYPE::KIBIS_DIFFDEVICE: + case TYPE::KIBIS_DIFFDRIVER: return std::make_unique( aType ); case TYPE::RAWSPICE: diff --git a/eeschema/sim/sim_model.h b/eeschema/sim/sim_model.h index 925532be29..f89ac806f1 100644 --- a/eeschema/sim/sim_model.h +++ b/eeschema/sim/sim_model.h @@ -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( m_pins.size() ); } @@ -517,7 +519,7 @@ public: int GetParamCount() const { return static_cast( 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 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 m_spiceGenerator; - const SIM_MODEL* m_baseModel; const TYPE m_type; std::vector m_pins; diff --git a/eeschema/sim/sim_model_kibis.cpp b/eeschema/sim/sim_model_kibis.cpp index 2696f36cdb..ee36983e88 100644 --- a/eeschema/sim/sim_model_kibis.cpp +++ b/eeschema/sim/sim_model_kibis.cpp @@ -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 kibisparam_driver_highz = makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_HIGHZ ); + static std::vector kibisparam_driver_prbs = + makeKibisParamInfos( SIM_MODEL::TYPE::KIBIS_DRIVER, SIM_MODEL_KIBIS::DRIVER_PRBS ); static std::vector 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; } diff --git a/eeschema/sim/sim_model_kibis.h b/eeschema/sim/sim_model_kibis.h index 48a8b33e0b..6fd1d81e66 100644 --- a/eeschema/sim/sim_model_kibis.h +++ b/eeschema/sim/sim_model_kibis.h @@ -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& aFields ); SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource, const std::vector& 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 ); diff --git a/pcbnew/ibis/kibis.cpp b/pcbnew/ibis/kibis.cpp index 2bb00cb7cc..7616ef24e7 100644 --- a/pcbnew/ibis/kibis.cpp +++ b/pcbnew/ibis/kibis.cpp @@ -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::vectorstimuliIndex; IbisWaveform risingWF = TrimWaveform( *( aPair.first ) ); IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) ); @@ -495,15 +496,23 @@ std::string KIBIS_MODEL::generateSquareWave( std::string aNode1, std::string aNo double delta = deltaR + deltaF; int i = 0; + + int prevBit = 2; + for( std::pair 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 ); @@ -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( wave ); + std::vector> 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 "; @@ -1413,4 +1453,39 @@ void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, std::string aSt aCorner = IBIS_CORNER::MAX; else aCorner = IBIS_CORNER::TYP; -} \ No newline at end of file +} + +std::vector> KIBIS_WAVEFORM_PRBS::GenerateBitSequence() +{ + std::vector> 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; + +} diff --git a/pcbnew/ibis/kibis.h b/pcbnew/ibis/kibis.h index 113606abad..7dae2fe27a 100644 --- a/pcbnew/ibis/kibis.h +++ b/pcbnew/ibis/kibis.h @@ -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> GenerateBitSequence(); + double GetDuration() override { return m_bits / m_bitrate ; }; }; class KIBIS_WAVEFORM_STUCK_HIGH : public KIBIS_WAVEFORM diff --git a/qa/ibis/qaIbisParser.cpp b/qa/ibis/qaIbisParser.cpp index 184ee028ed..7ceef568ea 100644 --- a/qa/ibis/qaIbisParser.cpp +++ b/qa/ibis/qaIbisParser.cpp @@ -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 );