KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kibis.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 Fabien Corona f.corona<at>laposte.net
5 * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
18 * to endorse or promote products derived from this software without specific
19 * prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33#include "kibis.h"
34#include "ibis_parser.h"
35#include <sstream>
36#include <sim/spice_simulator.h>
37
38
39// _() is used here to mark translatable strings in IBIS_REPORTER::Report()
40// However, currently non ASCII7 chars are nor correctly handled when printing messages
41// So we disable translations
42#if 0
43#include <wx/intl.h> // for _() macro and wxGetTranslation()
44#else
45#undef _
46#define _( x ) x
47#endif
48
49
50std::vector<std::pair<int, double>>
51SimplifyBitSequence( const std::vector<std::pair<int, double>>& bits )
52{
53 std::vector<std::pair<int, double>> result;
54 int prevbit = -1;
55
56 for( const std::pair<int, double>& bit : bits )
57 {
58 if( prevbit != bit.first )
59 result.push_back( bit );
60
61 prevbit = bit.first;
62 }
63
64 return result;
65}
66
67
68KIBIS_ANY::KIBIS_ANY( KIBIS* aTopLevel ) : KIBIS_ANY( aTopLevel, aTopLevel->m_reporter )
69{
70}
71
72KIBIS_ANY::KIBIS_ANY( KIBIS* aTopLevel, REPORTER* aReporter ) :
73 IBIS_ANY( aReporter ), m_topLevel( aTopLevel ), m_valid( false )
74{
75}
76
78{
80
81 if( aIn == IBIS_CORNER::MIN )
82 {
83 out = IBIS_CORNER::MAX;
84 }
85 else if( aIn == IBIS_CORNER::MAX )
86 {
87 out = IBIS_CORNER::MIN;
88 }
89
90 return out;
91}
92
93KIBIS::KIBIS( const std::string& aFileName, REPORTER* aReporter ) :
94 KIBIS_ANY( this, aReporter ), m_file( *this )
95{
96 IbisParser parser( m_reporter );
97 bool status = true;
98
99 parser.m_parrot = false;
100 status &= parser.ParseFile( aFileName );
101
102 status &= m_file.Init( parser );
103
104 for( const IbisModel& iModel : parser.m_ibisFile.m_models )
105 {
106 KIBIS_MODEL& kModel = m_models.emplace_back( *this, iModel, parser );
107 status &= kModel.m_valid;
108 }
109
110 for( const IbisComponent& iComponent : parser.m_ibisFile.m_components )
111 {
112 KIBIS_COMPONENT& kComponent = m_components.emplace_back( *this, iComponent, parser );
113 status &= kComponent.m_valid;
114
115 for( KIBIS_PIN& pin : kComponent.m_pins )
116 {
117 pin.m_parent = &kComponent;
118 }
119
120 for( const IbisDiffPinEntry& dpEntry : iComponent.m_diffPin.m_entries )
121 {
122 KIBIS_PIN* pinA = kComponent.GetPin( dpEntry.pinA );
123 KIBIS_PIN* pinB = kComponent.GetPin( dpEntry.pinB );
124
125 if( pinA && pinB )
126 {
127 pinA->m_complementaryPin = pinB;
128 pinB->m_complementaryPin = pinA;
129 }
130 }
131 }
132
133 m_valid = status;
134}
135
136
137KIBIS_FILE::KIBIS_FILE( KIBIS& aTopLevel ) : KIBIS_ANY( &aTopLevel )
138{
139 m_fileRev = -1;
140 m_ibisVersion = -1;
141}
142
143
144bool KIBIS_FILE::Init( const IbisParser& aParser )
145{
146 bool status = true;
154
155 m_valid = status;
156
157 return status;
158}
159
160
162 const IbisComponentPackage& aPackage, IbisParser& aParser,
163 KIBIS_COMPONENT* aParent, std::vector<KIBIS_MODEL>& aModels ) :
164 KIBIS_ANY( &aTopLevel ), m_Rpin( aTopLevel.m_reporter ), m_Lpin( aTopLevel.m_reporter ),
165 m_Cpin( aTopLevel.m_reporter )
166{
168 m_pinNumber = aPin.m_pinName;
169 m_parent = aParent;
170
171 m_Rpin = aPackage.m_Rpkg;
172 m_Lpin = aPackage.m_Lpkg;
173 m_Cpin = aPackage.m_Cpkg;
174
175 // The values listed in the [Pin] description section override the default
176 // values defined in [Package]
177
178 // @TODO : Reading the IBIS standard, I can't figure out if we are supposed
179 // to replace typ, min, and max, or just the typ ?
180
181 if( !std::isnan( aPin.m_Rpin ) )
182 {
183 m_Rpin.value[IBIS_CORNER::TYP] = aPin.m_Rpin;
184 m_Rpin.value[IBIS_CORNER::MIN] = aPin.m_Rpin;
185 m_Rpin.value[IBIS_CORNER::MAX] = aPin.m_Rpin;
186 }
187
188 if( !std::isnan( aPin.m_Lpin ) )
189 {
190 m_Lpin.value[IBIS_CORNER::TYP] = aPin.m_Lpin;
191 m_Lpin.value[IBIS_CORNER::MIN] = aPin.m_Lpin;
192 m_Lpin.value[IBIS_CORNER::MAX] = aPin.m_Lpin;
193 }
194
195 if( !std::isnan( aPin.m_Cpin ) )
196 {
197 m_Cpin.value[IBIS_CORNER::TYP] = aPin.m_Cpin;
198 m_Cpin.value[IBIS_CORNER::MIN] = aPin.m_Cpin;
199 m_Cpin.value[IBIS_CORNER::MAX] = aPin.m_Cpin;
200 }
201
202 bool modelSelected = false;
203 std::vector<std::string> listOfModels;
204
205 for( const IbisModelSelector& modelSelector : aParser.m_ibisFile.m_modelSelectors )
206 {
207 if( !strcmp( modelSelector.m_name.c_str(), aPin.m_modelName.c_str() ) )
208 {
209 for( const IbisModelSelectorEntry& model : modelSelector.m_models )
210 {
211 listOfModels.push_back( model.m_modelName );
212 }
213 modelSelected = true;
214 break;
215 }
216 }
217
218 if( !modelSelected )
219 {
220 listOfModels.push_back( aPin.m_modelName );
221 }
222
223 for( const std::string& modelName : listOfModels )
224 {
225 for( KIBIS_MODEL& model : aModels )
226 {
227 if( !strcmp( model.m_name.c_str(), modelName.c_str() ) )
228 {
229 m_models.push_back( &model );
230 }
231 }
232 }
233
234 m_valid = true;
235}
236
237
238KIBIS_MODEL::KIBIS_MODEL( KIBIS& aTopLevel, const IbisModel& aSource, IbisParser& aParser ) :
239 KIBIS_ANY( &aTopLevel ), m_C_comp( aTopLevel.m_reporter ),
240 m_voltageRange( aTopLevel.m_reporter ), m_temperatureRange( aTopLevel.m_reporter ),
241 m_pullupReference( aTopLevel.m_reporter ), m_pulldownReference( aTopLevel.m_reporter ),
242 m_GNDClampReference( aTopLevel.m_reporter ), m_POWERClampReference( aTopLevel.m_reporter ),
243 m_Rgnd( aTopLevel.m_reporter ), m_Rpower( aTopLevel.m_reporter ),
244 m_Rac( aTopLevel.m_reporter ), m_Cac( aTopLevel.m_reporter ),
245 m_GNDClamp( aTopLevel.m_reporter ), m_POWERClamp( aTopLevel.m_reporter ),
246 m_pullup( aTopLevel.m_reporter ), m_pulldown( aTopLevel.m_reporter ),
247 m_ramp( aTopLevel.m_reporter )
248{
249 bool status = true;
250
251 m_name = aSource.m_name;
252 m_type = aSource.m_type;
253
254 m_description = std::string( "No description available." );
255
256 for( const IbisModelSelector& modelSelector : aParser.m_ibisFile.m_modelSelectors )
257 {
258 for( const IbisModelSelectorEntry& entry : modelSelector.m_models )
259 {
260 if( !strcmp( entry.m_modelName.c_str(), m_name.c_str() ) )
261 {
263 }
264 }
265 }
266
267 m_vinh = aSource.m_vinh;
268 m_vinl = aSource.m_vinl;
269 m_vref = aSource.m_vref;
270 m_rref = aSource.m_rref;
271 m_cref = aSource.m_cref;
272 m_vmeas = aSource.m_vmeas;
273
274 m_enable = aSource.m_enable;
275 m_polarity = aSource.m_polarity;
276
277 m_ramp = aSource.m_ramp;
280 m_GNDClamp = aSource.m_GNDClamp;
282 m_POWERClamp = aSource.m_POWERClamp;
284
285 m_C_comp = aSource.m_C_comp;
290
291 m_Rgnd = aSource.m_Rgnd;
292 m_Rpower = aSource.m_Rpower;
293 m_Rac = aSource.m_Rac;
294 m_Cac = aSource.m_Cac;
295 m_pullup = aSource.m_pullup;
296 m_pulldown = aSource.m_pulldown;
297
298 m_valid = status;
299}
300
301
303 IbisParser& aParser ) : KIBIS_ANY( &aTopLevel )
304{
305 bool status = true;
306
307 m_name = aSource.m_name;
309
310 for( const IbisComponentPin& iPin : aSource.m_pins )
311 {
312 if( iPin.m_dummy )
313 {
314 continue;
315 }
316
317 KIBIS_PIN kPin( aTopLevel, iPin, aSource.m_package, aParser, nullptr,
319 status &= kPin.m_valid;
320 m_pins.push_back( kPin );
321 }
322
323 m_valid = status;
324}
325
326
327KIBIS_PIN* KIBIS_COMPONENT::GetPin( const std::string& aPinNumber )
328{
329 for( KIBIS_PIN& pin : m_pins )
330 {
331 if( pin.m_pinNumber == aPinNumber )
332 {
333 return &pin;
334 }
335 }
336
337 return nullptr;
338}
339
340std::vector<std::pair<IbisWaveform*, IbisWaveform*>> KIBIS_MODEL::waveformPairs()
341{
342 std::vector<std::pair<IbisWaveform*, IbisWaveform*>> pairs;
343 IbisWaveform* wf1;
344 IbisWaveform* wf2;
345
346 for( size_t i = 0; i < m_risingWaveforms.size(); i++ )
347 {
348 for( size_t j = 0; j < m_fallingWaveforms.size(); j++ )
349 {
350 wf1 = m_risingWaveforms.at( i );
351 wf2 = m_fallingWaveforms.at( j );
352
353 if( wf1->m_R_fixture == wf2->m_R_fixture && wf1->m_L_fixture == wf2->m_L_fixture
354 && wf1->m_C_fixture == wf2->m_C_fixture && wf1->m_V_fixture == wf2->m_V_fixture
355 && wf1->m_V_fixture_min == wf2->m_V_fixture_min
356 && wf1->m_V_fixture_max == wf2->m_V_fixture_max )
357 {
358 pairs.emplace_back( wf1, wf2 );
359 }
360 }
361 }
362
363 return pairs;
364}
365
366
367std::string KIBIS_MODEL::SpiceDie( const KIBIS_PARAMETER& aParam, int aIndex ) const
368{
369 std::string result;
370
371 std::string GC_GND = "GC_GND";
372 std::string PC_PWR = "PC_PWR";
373 std::string PU_PWR = "PU_PWR";
374 std::string PD_GND = "PD_GND";
375 std::string DIE = "DIE";
376 std::string DIEBUFF = "DIEBUFF";
377
378 IBIS_CORNER supply = aParam.m_supply;
379 IBIS_CORNER ccomp = aParam.m_Ccomp;
380
381 GC_GND += std::to_string( aIndex );
382 PC_PWR += std::to_string( aIndex );
383 PU_PWR += std::to_string( aIndex );
384 PD_GND += std::to_string( aIndex );
385 DIE += std::to_string( aIndex );
386 DIEBUFF += std::to_string( aIndex );
387
388
389 std::string GC = "GC";
390 std::string PC = "PC";
391 std::string PU = "PU";
392 std::string PD = "PD";
393
394 GC += std::to_string( aIndex );
395 PC += std::to_string( aIndex );
396 PU += std::to_string( aIndex );
397 PD += std::to_string( aIndex );
398
399 result = "\n";
400 result += "VPWR POWER GND ";
401 result += doubleToString( m_voltageRange.value[supply] );
402 result += "\n";
403 result += "CCPOMP " + DIE + " GND ";
404 result += doubleToString( m_C_comp.value[ccomp] );
405 result += "\n";
406
407 if( HasGNDClamp() )
408 {
409 result += m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, supply );
410 result += "VmeasGC GND " + GC_GND + " 0\n";
411 }
412
413 if( HasPOWERClamp() )
414 {
415 result += m_POWERClamp.Spice( aIndex * 4 + 2, "POWER", DIE, PC, supply );
416 result += "VmeasPC POWER " + PC_PWR + " 0\n";
417 }
418
419 if( HasPulldown() )
420 {
421 result += m_pulldown.Spice( aIndex * 4 + 3, DIEBUFF, PD_GND, PD, supply );
422 result += "VmeasPD GND " + PD_GND + " 0\n";
423 result += "BKD GND " + DIE + " i=( i(VmeasPD) * v(KD) )\n";
424 }
425
426 if( HasPullup() )
427 {
428 result += m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIEBUFF, PU, supply );
429 result += "VmeasPU POWER " + PU_PWR + " 0\n";
430 result += "BKU POWER " + DIE + " i=( -i(VmeasPU) * v(KU) )\n";
431 }
432
433 if ( HasPullup() || HasPulldown() )
434 result += "BDIEBUFF " + DIEBUFF + " GND v=v(" + DIE + ")\n";
435
436 return result;
437}
438
439
441{
442 IbisWaveform out( aIn.m_reporter );
443
444 const int nbPoints = aIn.m_table.m_entries.size();
445
446 if( nbPoints < 2 )
447 {
448 Report( _( "waveform has less than two points" ), RPT_SEVERITY_ERROR );
449 return out;
450 }
451
452 const double DCtyp = aIn.m_table.m_entries[0].V.value[IBIS_CORNER::TYP];
453 const double DCmin = aIn.m_table.m_entries[0].V.value[IBIS_CORNER::MIN];
454 const double DCmax = aIn.m_table.m_entries[0].V.value[IBIS_CORNER::MAX];
455
456 if( nbPoints == 2 )
457 {
458 return out;
459 }
460
461 out.m_table.m_entries.clear();
462
463 for( int i = 0; i < nbPoints; i++ )
464 {
465 const VTtableEntry& inEntry = aIn.m_table.m_entries.at( i );
466 VTtableEntry& outEntry = out.m_table.m_entries.emplace_back( out.m_reporter );
467
468 outEntry.t = inEntry.t;
469 outEntry.V.value[IBIS_CORNER::TYP] = inEntry.V.value[IBIS_CORNER::TYP] - DCtyp;
470 outEntry.V.value[IBIS_CORNER::MIN] = inEntry.V.value[IBIS_CORNER::MIN] - DCmin;
471 outEntry.V.value[IBIS_CORNER::MAX] = inEntry.V.value[IBIS_CORNER::MAX] - DCmax;
472 }
473
474 return out;
475}
476
477
479{
480 return m_pulldown.m_entries.size() > 0;
481}
482
483
485{
486 return m_pullup.m_entries.size() > 0;
487}
488
489
491{
492 return m_GNDClamp.m_entries.size() > 0;
493}
494
495
497{
498 return m_POWERClamp.m_entries.size() > 0;
499}
500
501
502std::string KIBIS_MODEL::generateSquareWave( const std::string& aNode1, const std::string& aNode2,
503 const std::vector<std::pair<int, double>>& aBits,
504 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
505 const KIBIS_PARAMETER& aParam )
506{
507 const IBIS_CORNER supply = aParam.m_supply;
508 std::string simul;
509 std::vector<int> stimuliIndex;
510
511 IbisWaveform risingWF = TrimWaveform( *( aPair.first ) );
512 IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) );
513
514 double deltaR = risingWF.m_table.m_entries.back().V.value[supply]
515 - risingWF.m_table.m_entries.at( 0 ).V.value[supply];
516 double deltaF = fallingWF.m_table.m_entries.back().V.value[supply]
517 - fallingWF.m_table.m_entries.at( 0 ).V.value[supply];
518
519 // Ideally, delta should be equal to zero.
520 // It can be different from zero if the falling waveform does not start were the rising one ended.
521 double delta = deltaR + deltaF;
522
523 int i = 0;
524
525 int prevBit = 2;
526
527 for( const std::pair<int, double>& bit : aBits )
528 {
530 double timing = bit.second;
531
532
533 if ( bit.first != prevBit )
534 {
535 if( bit.first == 1 )
536 WF = &risingWF;
537 else
538 WF = &fallingWF;
539
540 stimuliIndex.push_back( i );
541
542 simul += "Vstimuli";
543 simul += std::to_string( i );
544 simul += " stimuli";
545 simul += std::to_string( i );
546 simul += " ";
547 simul += aNode2;
548 simul += " pwl ( \n+";
549
550 if( i != 0 )
551 {
552 simul += "0 0 ";
553 VTtableEntry entry0 = WF->m_table.m_entries.at( 0 );
554 VTtableEntry entry1 = WF->m_table.m_entries.at( 1 );
555 double deltaT = entry1.t - entry0.t;
556
557 simul += doubleToString( entry0.t + timing - deltaT );
558 simul += " ";
559 simul += "0";
560 simul += "\n+";
561 }
562
563 for( const VTtableEntry& entry : WF->m_table.m_entries )
564 {
565 simul += doubleToString( entry.t + timing );
566 simul += " ";
567 simul += doubleToString( entry.V.value[supply] - delta );
568 simul += "\n+";
569 }
570 simul += ")\n";
571 }
572
573 i++;
574 prevBit = bit.first;
575 }
576
577 simul += "bin ";
578 simul += aNode1;
579 simul += " ";
580 simul += aNode2;
581 simul += " v=(";
582
583 for( int ii: stimuliIndex )
584 {
585 simul += " v( stimuli";
586 simul += std::to_string( ii );
587 simul += " ) +\n+";
588 }
589
590 // Depending on the first bit, we add a different DC value
591 // The DC value we add is the first value of the first bit.
592 if( ( aBits.size() > 0 ) && ( aBits[0].first == 0 ) )
593 {
594 simul += doubleToString( aPair.second->m_table.m_entries.at( 0 ).V.value[supply] );
595 }
596 else
597 {
598 simul += doubleToString( aPair.first->m_table.m_entries.at( 0 ).V.value[supply] );
599 }
600
601 simul += ")\n";
602 return simul;
603}
604
605
606std::string KIBIS_PIN::addDie( KIBIS_MODEL& aModel, const KIBIS_PARAMETER& aParam, int aIndex )
607{
608 const IBIS_CORNER supply = aParam.m_supply;
609 std::string simul;
610
611 std::string GC_GND = "GC_GND";
612 std::string PC_PWR = "PC_PWR";
613 std::string PU_PWR = "PU_PWR";
614 std::string PD_GND = "PD_GND";
615 std::string DIE = "DIE";
616
617 GC_GND += std::to_string( aIndex );
618 PC_PWR += std::to_string( aIndex );
619 PU_PWR += std::to_string( aIndex );
620 PD_GND += std::to_string( aIndex );
621 DIE += std::to_string( aIndex );
622
623
624 std::string GC = "GC";
625 std::string PC = "PC";
626 std::string PU = "PU";
627 std::string PD = "PD";
628
629 GC += std::to_string( aIndex );
630 PC += std::to_string( aIndex );
631 PU += std::to_string( aIndex );
632 PD += std::to_string( aIndex );
633
634 if( aModel.HasGNDClamp() )
635 {
636 simul += aModel.m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, supply );
637 }
638
639 if( aModel.HasPOWERClamp() )
640 {
641 simul += aModel.m_POWERClamp.Spice( aIndex * 4 + 2, PC_PWR, DIE, PC, supply );
642 }
643
644 if( aModel.HasPulldown() )
645 {
646 simul += aModel.m_pulldown.Spice( aIndex * 4 + 3, DIE, PD_GND, PD, supply );
647 }
648
649 if( aModel.HasPullup() )
650 {
651 simul += aModel.m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIE, PU, supply );
652 }
653
654 return simul;
655}
656
657
658void KIBIS_PIN::getKuKdFromFile( const std::string& aSimul )
659{
660 const std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
661
662 if( std::remove( outputFileName.c_str() ) )
663 {
664 Report( _( "Cannot remove temporary output file" ), RPT_SEVERITY_WARNING );
665 }
666
667 std::shared_ptr<SPICE_SIMULATOR> ng = SIMULATOR::CreateInstance( "ng-kibis" );
668
669 if( !ng )
670 {
671 throw std::runtime_error( "Could not create simulator instance" );
672 return;
673 }
674 ng->Init();
675 ng->LoadNetlist( aSimul );
676
677 std::ifstream KuKdfile;
678 KuKdfile.open( outputFileName );
679
680 std::vector<double> ku, kd, t;
681 if( KuKdfile )
682 {
683 std::string line;
684
685 for( int i = 0; i < 11; i++ ) // number of line in the ngspice output header
686 {
687 std::getline( KuKdfile, line );
688 }
689
690 int i = 0;
691 double t_v, ku_v, kd_v;
692
693 while( KuKdfile )
694 {
695 std::getline( KuKdfile, line );
696
697 if( line.empty() )
698 {
699 continue;
700 }
701
702 switch( i )
703 {
704 case 0:
705 line = line.substr( line.find_first_of( "\t" ) + 1 );
706 t_v = std::stod( line );
707 break;
708 case 1: ku_v = std::stod( line ); break;
709 case 2:
710 kd_v = std::stod( line );
711 ku.push_back( ku_v );
712 kd.push_back( kd_v );
713 t.push_back( t_v );
714 break;
715 default: Report( _( "Error while reading temporary file" ), RPT_SEVERITY_ERROR );
716 }
717 i = ( i + 1 ) % 3;
718 }
719
720 std::getline( KuKdfile, line );
721 }
722 else
723 {
724 Report( _( "Error while creating temporary output file" ), RPT_SEVERITY_ERROR );
725 }
726
727 if( std::remove( outputFileName.c_str() ) )
728 {
729 Report( _( "Cannot remove temporary output file" ), RPT_SEVERITY_WARNING );
730 }
731
732 m_Ku = ku;
733 m_Kd = kd;
734 m_t = t;
735}
736
737
739 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
740 const KIBIS_PARAMETER& aParam, int aIndex )
741{
742 IBIS_CORNER supply = aParam.m_supply;
743 IBIS_CORNER ccomp = aParam.m_Ccomp;
744 KIBIS_WAVEFORM* wave = aParam.m_waveform;
745
746 std::string simul = "";
747
748 simul += "*THIS IS NOT A VALID SPICE MODEL.\n";
749 simul += "*This part is intended to be executed by Kibis internally.\n";
750 simul += "*You should not be able to read this.\n\n";
751
752 simul += ".SUBCKT DRIVER";
753 simul += std::to_string( aIndex );
754 simul += " POWER GND PIN \n"; // 1: POWER, 2:GND, 3:PIN
755
756 simul += "Vdummy 2 PIN 0\n";
757
758 if( ( aPair.first->m_R_dut != 0 ) || ( aPair.first->m_L_dut != 0 )
759 || ( aPair.first->m_C_dut != 0 ) )
760 {
761 Report( _( "Kibis does not support DUT values yet. "
762 "https://ibis.org/summits/nov16a/chen.pdf" ),
764 }
765
766 simul += "\n";
767 simul += "CCPOMP 2 GND ";
768 simul += doubleToString( aModel.m_C_comp.value[ccomp] ); //@TODO: Check the corner ?
769 simul += "\n";
770
771 const IbisWaveform* risingWF = aPair.first;
772 const IbisWaveform* fallingWF = aPair.second;
773
774 switch( wave->GetType() )
775 {
776 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
777 case KIBIS_WAVEFORM_TYPE::PRBS:
778 {
779 wave->Check( risingWF, fallingWF );
780 std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
781 bits = SimplifyBitSequence( bits );
782 simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
783 break;
784 }
785 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
786 {
787 const IbisWaveform* waveform = wave->inverted ? risingWF : fallingWF;
788 simul += "Vsig DIE0 GND ";
789 simul += doubleToString( waveform->m_table.m_entries.at( 0 ).V.value[supply] );
790 simul += "\n";
791 break;
792 }
793 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
794 {
795 const IbisWaveform* waveform = wave->inverted ? fallingWF : risingWF;
796 simul += "Vsig DIE0 GND ";
797 simul += doubleToString( waveform->m_table.m_entries.at( 0 ).V.value[supply] );
798 simul += "\n";
799 break;
800 }
801 case KIBIS_WAVEFORM_TYPE::NONE:
802 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
803 default: break;
804 }
805 simul += addDie( aModel, aParam, 0 );
806
807 simul += "\n.ENDS DRIVER\n\n";
808 return simul;
809}
810
811
813 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
814 const KIBIS_PARAMETER& aParam )
815{
816 IBIS_CORNER supply = aParam.m_supply;
817 const KIBIS_WAVEFORM* wave = aParam.m_waveform;
818
819 std::string simul = "";
820
821 if( !wave )
822 return;
823
824 if( wave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
825 {
826 //@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
827 std::vector<double> ku, kd, t;
828 ku.push_back( 0 );
829 kd.push_back( 0 );
830 t.push_back( 0 );
831 m_Ku = ku;
832 m_Kd = kd;
833 m_t = t;
834 }
835 else
836 {
837 simul += KuKdDriver( aModel, aPair, aParam, 0 );
838 simul += "\n x1 3 0 1 DRIVER0 \n";
839
840 simul += "VCC 3 0 ";
841 simul += doubleToString( aModel.m_voltageRange.value[supply] );
842 simul += "\n";
843 //simul += "Vpin x1.DIE 0 1 \n"
844 simul += "Lfixture 1 4 ";
845 simul += doubleToString( aPair.first->m_L_fixture );
846 simul += "\n";
847 simul += "Rfixture 4 5 ";
848 simul += doubleToString( aPair.first->m_R_fixture );
849 simul += "\n";
850 simul += "Cfixture 4 0 ";
851 simul += doubleToString( aPair.first->m_C_fixture );
852 simul += "\n";
853 simul += "Vfixture 5 0 ";
854 simul += doubleToString( aPair.first->m_V_fixture );
855 simul += "\n";
856 simul += "VmeasIout x1.DIE0 x1.2 0\n";
857 simul += "VmeasPD 0 x1.PD_GND0 0\n";
858 simul += "VmeasPU x1.PU_PWR0 3 0\n";
859 simul += "VmeasPC x1.PC_PWR0 3 0\n";
860 simul += "VmeasGC 0 x1.GC_GND0 0\n";
861
862 if( aModel.HasPullup() && aModel.HasPulldown() )
863 {
864 Report( _( "Model has only one waveform pair, reduced accuracy" ),
866 simul += "Bku KU 0 v=( (i(VmeasIout)-i(VmeasPC)-i(VmeasGC)-i(VmeasPD) "
867 ")/(i(VmeasPU)-i(VmeasPD)))\n";
868 simul += "Bkd KD 0 v=(1-v(KU))\n";
869 }
870
871 else if( !aModel.HasPullup() && aModel.HasPulldown() )
872 {
873 simul += "Bku KD 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPD)))\n";
874 simul += "Bkd KU 0 v=0\n";
875 }
876
877 else if( aModel.HasPullup() && !aModel.HasPulldown() )
878 {
879 simul += "Bku KU 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPU)))\n";
880 simul += "Bkd KD 0 v=0\n";
881 }
882 else
883 {
884 Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
885 }
886
887 switch( wave->GetType() )
888 {
889 case KIBIS_WAVEFORM_TYPE::PRBS:
890 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
891 {
892 double duration = wave->GetDuration();
893 simul += ".tran 0.1n ";
894 simul += doubleToString( duration );
895 simul += "\n";
896 break;
897 }
898 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
899 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
900 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
901 default: simul += ".tran 0.5 1 \n"; //
902 }
903 //simul += ".dc Vpin -5 5 0.1\n";
904 simul += ".control run \n";
905 simul += "set filetype=ascii\n";
906 simul += "run \n";
907 //simul += "plot v(x1.DIE0) i(VmeasIout) i(VmeasPD) i(VmeasPU) i(VmeasPC) i(VmeasGC)\n";
908 //simul += "plot v(KU) v(KD)\n";
909
910 std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
911 simul += "write '" + outputFileName + "' v(KU) v(KD)\n";
912 simul += "quit\n";
913 simul += ".endc \n";
914 simul += ".end \n";
915
916 getKuKdFromFile( simul );
917 }
918}
919
920
922{
923 std::vector<double> ku, kd, t;
924 const KIBIS_WAVEFORM* wave = aParam.m_waveform;
925 const IBIS_CORNER& supply = aParam.m_supply;
926
927 if( !wave )
928 {
929 return;
930 }
931
932 switch( wave->GetType() )
933 {
934 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
935 case KIBIS_WAVEFORM_TYPE::PRBS:
936 {
937 wave->Check( aModel.m_ramp.m_rising, aModel.m_ramp.m_falling );
938 std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
939 bits = SimplifyBitSequence( bits );
940
941 for( const std::pair<int, double>& bit : bits )
942 {
943 ku.push_back( bit.first ? 0 : 1 );
944 kd.push_back( bit.first ? 1 : 0 );
945 t.push_back( bit.second );
946 ku.push_back( bit.first ? 1 : 0 );
947 kd.push_back( bit.first ? 0 : 1 );
948 t.push_back( bit.second
949 + ( bit.first ? +aModel.m_ramp.m_rising.value[supply].m_dt
950 : aModel.m_ramp.m_falling.value[supply].m_dt )
951 / 0.6 );
952 // 0.6 because ibis only gives 20%-80% time
953 }
954 break;
955 }
956 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
957 {
958 ku.push_back( wave->inverted ? 0 : 1 );
959 kd.push_back( wave->inverted ? 1 : 0 );
960 t.push_back( 0 );
961 break;
962 }
963 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
964 {
965 ku.push_back( wave->inverted ? 1 : 0 );
966 kd.push_back( wave->inverted ? 0 : 1 );
967 t.push_back( 0 );
968 break;
969 }
970 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
971 case KIBIS_WAVEFORM_TYPE::NONE:
972 default:
973 ku.push_back( 0 );
974 kd.push_back( 0 );
975 t.push_back( 0 );
976 }
977 m_Ku = ku;
978 m_Kd = kd;
979 m_t = t;
980}
981
982
984 const std::pair<IbisWaveform*, IbisWaveform*>& aPair1,
985 const std::pair<IbisWaveform*, IbisWaveform*>& aPair2,
986 const KIBIS_PARAMETER& aParam )
987{
988 std::string simul = "";
989 const IBIS_CORNER supply = aParam.m_supply;
990 const KIBIS_WAVEFORM* wave = aParam.m_waveform;
991
992 if( !wave )
993 return;
994
995 if( wave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
996 {
997 //@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
998 std::vector<double> ku, kd, t;
999 ku.push_back( 0 );
1000 kd.push_back( 0 );
1001 t.push_back( 0 );
1002 m_Ku = ku;
1003 m_Kd = kd;
1004 m_t = t;
1005 }
1006 else
1007 {
1008 simul += KuKdDriver( aModel, aPair1, aParam, 0 );
1009 simul += KuKdDriver( aModel, aPair2, aParam, 1 );
1010 simul += "\n x1 3 0 1 DRIVER0 \n";
1011
1012 simul += "VCC 3 0 ";
1013 simul += doubleToString( aModel.m_voltageRange.value[supply] );
1014 simul += "\n";
1015 //simul += "Vpin x1.DIE 0 1 \n"
1016 simul += "Lfixture0 1 4 ";
1017 simul += doubleToString( aPair1.first->m_L_fixture );
1018 simul += "\n";
1019 simul += "Rfixture0 4 5 ";
1020 simul += doubleToString( aPair1.first->m_R_fixture );
1021 simul += "\n";
1022 simul += "Cfixture0 4 0 ";
1023 simul += doubleToString( aPair1.first->m_C_fixture );
1024 simul += "\n";
1025 simul += "Vfixture0 5 0 ";
1026 simul += doubleToString( aPair1.first->m_V_fixture );
1027 simul += "\n";
1028 simul += "VmeasIout0 x1.2 x1.DIE0 0\n";
1029 simul += "VmeasPD0 0 x1.PD_GND0 0\n";
1030 simul += "VmeasPU0 x1.PU_PWR0 3 0\n";
1031 simul += "VmeasPC0 x1.PC_PWR0 3 0\n";
1032 simul += "VmeasGC0 0 x1.GC_GND0 0\n";
1033
1034
1035 simul += "\n x2 3 0 7 DRIVER1 \n";
1036 //simul += "Vpin x1.DIE 0 1 \n"
1037 simul += "Lfixture1 7 8 ";
1038 simul += doubleToString( aPair2.first->m_L_fixture );
1039 simul += "\n";
1040 simul += "Rfixture1 8 9 ";
1041 simul += doubleToString( aPair2.first->m_R_fixture );
1042 simul += "\n";
1043 simul += "Cfixture1 8 0 ";
1044 simul += doubleToString( aPair2.first->m_C_fixture );
1045 simul += "\n";
1046 simul += "Vfixture1 9 0 ";
1047 simul += doubleToString( aPair2.first->m_V_fixture );
1048 simul += "\n";
1049 simul += "VmeasIout1 x2.2 x2.DIE0 0\n";
1050 simul += "VmeasPD1 0 x2.PD_GND0 0\n";
1051 simul += "VmeasPU1 x2.PU_PWR0 3 0\n";
1052 simul += "VmeasPC1 x2.PC_PWR0 3 0\n";
1053 simul += "VmeasGC1 0 x2.GC_GND0 0\n";
1054
1055 if( aModel.HasPullup() && aModel.HasPulldown() )
1056 {
1057 simul +=
1058 "Bku KU 0 v=( ( i(VmeasPD1) * ( i(VmeasIout0) + i(VmeasPC0) + i(VmeasGC0) ) - "
1059 "i(VmeasPD0) * ( i(VmeasIout1) + i(VmeasPC1) + i(VmeasGC1) ) )/ ( i(VmeasPU1) "
1060 "* "
1061 "i(VmeasPD0) - i(VmeasPU0) * i(VmeasPD1) ) )\n";
1062 simul +=
1063 "Bkd KD 0 v=( ( i(VmeasPU1) * ( i(VmeasIout0) + i(VmeasPC0) + i(VmeasGC0) ) - "
1064 "i(VmeasPU0) * ( i(VmeasIout1) + i(VmeasPC1) + i(VmeasGC1) ) )/ ( i(VmeasPD1) "
1065 "* "
1066 "i(VmeasPU0) - i(VmeasPD0) * i(VmeasPU1) ) )\n";
1067 //simul += "Bkd KD 0 v=(1-v(KU))\n";
1068 }
1069
1070 else if( !aModel.HasPullup() && aModel.HasPulldown() )
1071 {
1072 Report( _( "There are two waveform pairs, but only one transistor. More equations than "
1073 "unknowns." ),
1075 simul += "Bku KD 0 v=( ( i(VmeasIout0)+i(VmeasPC0)+i(VmeasGC0) )/(i(VmeasPD0)))\n";
1076 simul += "Bkd KU 0 v=0\n";
1077 }
1078
1079 else if( aModel.HasPullup() && !aModel.HasPulldown() )
1080 {
1081 Report( _( "There are two waveform pairs, but only one transistor. More equations than "
1082 "unknowns." ),
1084 simul += "Bku KU 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPU)))\n";
1085 simul += "Bkd KD 0 v=0\n";
1086 }
1087 else
1088 {
1089 Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
1090 }
1091
1092 switch( wave->GetType() )
1093 {
1094 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
1095 case KIBIS_WAVEFORM_TYPE::PRBS:
1096 {
1097 double duration = wave->GetDuration();
1098 simul += ".tran 0.1n ";
1099 simul += doubleToString( duration );
1100 simul += "\n";
1101 break;
1102 }
1103 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
1104 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
1105 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
1106 default: simul += ".tran 0.5 1 \n"; //
1107 }
1108 //simul += ".dc Vpin -5 5 0.1\n";
1109 simul += ".control run \n";
1110 simul += "set filetype=ascii\n";
1111 simul += "run \n";
1112 simul += "plot v(KU) v(KD)\n";
1113 //simul += "plot v(x1.DIE0) \n";
1114 std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
1115 simul += "write '" + outputFileName + "' v(KU) v(KD)\n";
1116 simul += "quit\n";
1117 simul += ".endc \n";
1118 simul += ".end \n";
1119
1120 getKuKdFromFile( simul );
1121 }
1122}
1123
1124
1125bool KIBIS_PIN::writeSpiceDriver( std::string& aDest, const std::string& aName, KIBIS_MODEL& aModel,
1126 const KIBIS_PARAMETER& aParam )
1127{
1128 bool status = true;
1129
1130 switch( aModel.m_type )
1131 {
1132 case IBIS_MODEL_TYPE::OUTPUT:
1133 case IBIS_MODEL_TYPE::IO:
1134 case IBIS_MODEL_TYPE::THREE_STATE:
1135 case IBIS_MODEL_TYPE::OPEN_DRAIN:
1136 case IBIS_MODEL_TYPE::IO_OPEN_DRAIN:
1137 case IBIS_MODEL_TYPE::OPEN_SINK:
1138 case IBIS_MODEL_TYPE::IO_OPEN_SINK:
1139 case IBIS_MODEL_TYPE::OPEN_SOURCE:
1140 case IBIS_MODEL_TYPE::IO_OPEN_SOURCE:
1141 case IBIS_MODEL_TYPE::OUTPUT_ECL:
1142 case IBIS_MODEL_TYPE::IO_ECL:
1143 case IBIS_MODEL_TYPE::THREE_STATE_ECL:
1144 {
1145 std::string result;
1146 std::string tmp;
1147
1148 result = "\n*Driver model generated by Kicad using Ibis data. ";
1149 result += "\n*Component: ";
1150
1151 if( m_parent )
1152 {
1153 //result += m_parent->m_name;
1154 }
1155 result += "\n*Manufacturer: ";
1156
1157 if( m_parent )
1158 {
1159 //result += m_parent->m_manufacturer;
1160 }
1161 result += "\n*Pin number: ";
1162 result += m_pinNumber;
1163 result += "\n*Signal name: ";
1164 result += m_signalName;
1165 result += "\n*Model: ";
1166 result += aModel.m_name;
1167 result += "\n.SUBCKT ";
1168 result += aName;
1169 result += " GND PIN \n";
1170 result += "\n";
1171
1172 result += "RPIN 1 PIN ";
1173 result += doubleToString( m_Rpin.value[aParam.m_Rpin] );
1174 result += "\n";
1175 result += "LPIN DIE0 1 ";
1176 result += doubleToString( m_Lpin.value[aParam.m_Lpin] );
1177 result += "\n";
1178 result += "CPIN PIN GND ";
1179 result += doubleToString( m_Cpin.value[aParam.m_Cpin] );
1180 result += "\n";
1181
1182 std::vector<std::pair<IbisWaveform*, IbisWaveform*>> wfPairs = aModel.waveformPairs();
1183 KIBIS_ACCURACY accuracy = aParam.m_accuracy;
1184
1185 if( wfPairs.size() < 1 || accuracy <= KIBIS_ACCURACY::LEVEL_0 )
1186 {
1187 if( accuracy > KIBIS_ACCURACY::LEVEL_0 )
1188 {
1189 Report( _( "Model has no waveform pair, using [Ramp] instead, poor accuracy" ),
1191 }
1192 getKuKdNoWaveform( aModel, aParam );
1193 }
1194 else if( wfPairs.size() == 1 || accuracy <= KIBIS_ACCURACY::LEVEL_1 )
1195 {
1196 getKuKdOneWaveform( aModel, wfPairs.at( 0 ), aParam );
1197 }
1198 else
1199 {
1200 if( wfPairs.size() > 2 || accuracy <= KIBIS_ACCURACY::LEVEL_2 )
1201 {
1202 Report( _( "Model has more than 2 waveform pairs, using the first two." ),
1204 }
1205 getKuKdTwoWaveforms( aModel, wfPairs.at( 0 ), wfPairs.at( 1 ), aParam );
1206 }
1207
1208 result += "Vku KU GND pwl ( ";
1209
1210 for( size_t i = 0; i < m_t.size(); i++ )
1211 {
1212 result += doubleToString( m_t.at( i ) );
1213 result += " ";
1214 result += doubleToString( m_Ku.at( i ) );
1215 result += " ";
1216 }
1217
1218 result += ") \n";
1219
1220
1221 result += "Vkd KD GND pwl ( ";
1222
1223 for( size_t i = 0; i < m_t.size(); i++ )
1224 {
1225 result += doubleToString( m_t.at( i ) );
1226 result += " ";
1227 result += doubleToString( m_Kd.at( i ) );
1228 result += " ";
1229 }
1230
1231 result += ") \n";
1232
1233 result += aModel.SpiceDie( aParam, 0 );
1234
1235 result += "\n.ENDS DRIVER\n\n";
1236
1237 aDest += result;
1238 break;
1239 }
1240 default: Report( _( "Invalid model type for a driver." ), RPT_SEVERITY_ERROR ); status = false;
1241 }
1242
1243 return status;
1244}
1245
1246
1247bool KIBIS_PIN::writeSpiceDevice( std::string& aDest, const std::string& aName, KIBIS_MODEL& aModel,
1248 const KIBIS_PARAMETER& aParam )
1249{
1250 bool status = true;
1251
1252 switch( aModel.m_type )
1253 {
1254 case IBIS_MODEL_TYPE::INPUT_STD:
1255 case IBIS_MODEL_TYPE::IO:
1256 case IBIS_MODEL_TYPE::IO_OPEN_DRAIN:
1257 case IBIS_MODEL_TYPE::IO_OPEN_SINK:
1258 case IBIS_MODEL_TYPE::IO_OPEN_SOURCE:
1259 case IBIS_MODEL_TYPE::IO_ECL:
1260 {
1261 std::string result;
1262
1263 result += "\n";
1264 result = "*Device model generated by Kicad using Ibis data.";
1265 result += "\n.SUBCKT ";
1266 result += aName;
1267 result += " GND PIN\n";
1268 result += "\n";
1269 result += "\n";
1270 result += "RPIN 1 PIN ";
1271 result += doubleToString( m_Rpin.value[aParam.m_Rpin] );
1272 result += "\n";
1273 result += "LPIN DIE0 1 ";
1274 result += doubleToString( m_Lpin.value[aParam.m_Lpin] );
1275 result += "\n";
1276 result += "CPIN PIN GND ";
1277 result += doubleToString( m_Cpin.value[aParam.m_Cpin] );
1278 result += "\n";
1279
1280
1281 result += "Vku KU GND pwl ( 0 0 )\n";
1282 result += "Vkd KD GND pwl ( 0 0 )\n";
1283
1284 result += aModel.SpiceDie( aParam, 0 );
1285
1286 result += "\n.ENDS DRIVER\n\n";
1287
1288 aDest = std::move( result );
1289 break;
1290 }
1291 default: Report( _( "Invalid model type for a device" ), RPT_SEVERITY_ERROR ); status = false;
1292 }
1293
1294 return status;
1295}
1296
1297
1298bool KIBIS_PIN::writeSpiceDiffDriver( std::string& aDest, const std::string& aName,
1299 KIBIS_MODEL& aModel, const KIBIS_PARAMETER& aParam )
1300{
1301 bool status = true;
1302 KIBIS_WAVEFORM* wave = aParam.m_waveform;
1303
1304 if( !wave )
1305 return false;
1306
1307 std::string result;
1308 result = "\n*Differential driver model generated by Kicad using Ibis data. ";
1309 result += "\n*Component: ";
1310
1311 if( m_parent )
1312 {
1313 //result += m_parent->m_name;
1314 }
1315 result += "\n*Manufacturer: ";
1316
1317 if( m_parent )
1318 {
1319 //result += m_parent->m_manufacturer;
1320 }
1321
1322 result += "\n.SUBCKT ";
1323 result += aName;
1324 result += " GND PIN_P PIN_N\n";
1325 result += "\n";
1326
1327 status &= writeSpiceDriver( result, aName + "_P", aModel, aParam );
1328 wave->inverted = !wave->inverted;
1329 status &= writeSpiceDriver( result, aName + "_N", aModel, aParam );
1330 wave->inverted = !wave->inverted;
1331
1332
1333 result += "\n";
1334 result += "x1 GND PIN_P " + aName + "_P \n";
1335 result += "x2 GND PIN_N " + aName + "_N \n";
1336 result += "\n";
1337
1338 result += "\n.ENDS " + aName + "\n\n";
1339
1340 if( status )
1341 {
1342 aDest += result;
1343 }
1344
1345 return status;
1346}
1347
1348
1349bool KIBIS_PIN::writeSpiceDiffDevice( std::string& aDest, const std::string& aName,
1350 KIBIS_MODEL& aModel, const KIBIS_PARAMETER& aParam )
1351{
1352 bool status = true;
1353
1354 std::string result;
1355 result = "\n*Differential device model generated by Kicad using Ibis data. ";
1356 result += "\n*Component: ";
1357
1358 if( m_parent )
1359 {
1360 //result += m_parent->m_name;
1361 }
1362 result += "\n*Manufacturer: ";
1363
1364 if( m_parent )
1365 {
1366 //result += m_parent->m_manufacturer;
1367 }
1368
1369 result += "\n.SUBCKT ";
1370 result += aName;
1371 result += " GND PIN_P PIN_N\n";
1372 result += "\n";
1373
1374 status &= writeSpiceDevice( result, aName + "_P", aModel, aParam );
1375 status &= writeSpiceDevice( result, aName + "_N", aModel, aParam );
1376
1377 result += "\n";
1378 result += "x1 GND PIN_P " + aName + "_P \n";
1379 result += "x2 GND PIN_N " + aName + "_N \n";
1380 result += "\n";
1381
1382 result += "\n.ENDS " + aName + "\n\n";
1383
1384 if( status )
1385 {
1386 aDest += result;
1387 }
1388
1389 return status;
1390}
1391
1392
1393KIBIS_MODEL* KIBIS::GetModel( const std::string& aName )
1394{
1395 for( KIBIS_MODEL& model : m_models )
1396 {
1397 if( model.m_name == aName )
1398 return &model;
1399 }
1400 return nullptr;
1401}
1402
1403
1404KIBIS_COMPONENT* KIBIS::GetComponent( const std::string& aName )
1405{
1406 for( KIBIS_COMPONENT& cmp : m_components )
1407 {
1408 if( cmp.m_name == aName )
1409 return &cmp;
1410 }
1411 return nullptr;
1412}
1413
1414
1415void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, const std::string& aString )
1416{
1417 if( aString == "MIN" )
1418 aCorner = IBIS_CORNER::MIN;
1419 else if( aString == "MAX" )
1420 aCorner = IBIS_CORNER::MAX;
1421 else
1422 aCorner = IBIS_CORNER::TYP;
1423}
1424
1425
1426std::vector<std::pair<int, double>> KIBIS_WAVEFORM_STUCK_HIGH::GenerateBitSequence() const
1427{
1428 std::vector<std::pair<int, double>> bits;
1429 std::pair<int, double> bit;
1430 bit.first = inverted ? 1 : 0;
1431 bit.second = 0;
1432 return bits;
1433}
1434
1435
1436std::vector<std::pair<int, double>> KIBIS_WAVEFORM_STUCK_LOW::GenerateBitSequence() const
1437{
1438 std::vector<std::pair<int, double>> bits;
1439 std::pair<int, double> bit;
1440 bit.first = inverted ? 0 : 1;
1441 bit.second = 0;
1442 return bits;
1443}
1444
1445std::vector<std::pair<int, double>> KIBIS_WAVEFORM_HIGH_Z::GenerateBitSequence() const
1446{
1447 std::vector<std::pair<int, double>> bits;
1448 return bits;
1449}
1450
1451std::vector<std::pair<int, double>> KIBIS_WAVEFORM_RECTANGULAR::GenerateBitSequence() const
1452{
1453 std::vector<std::pair<int, double>> bits;
1454
1455 for( int i = 0; i < m_cycles; i++ )
1456 {
1457 std::pair<int, double> bit;
1458 bit.first = inverted ? 0 : 1;
1459 bit.second = ( m_ton + m_toff ) * i + m_delay;
1460 bits.push_back( bit );
1461
1462 bit.first = inverted ? 1 : 0;
1463 bit.second = ( m_ton + m_toff ) * i + m_delay + m_ton;
1464 bits.push_back( bit );
1465 }
1466 return bits;
1467}
1468
1469
1470std::vector<std::pair<int, double>> KIBIS_WAVEFORM_PRBS::GenerateBitSequence() const
1471{
1472 std::vector<std::pair<int, double>> bitSequence;
1473 uint8_t polynomial = 0b1100000;
1474 //1100000 = x^7+x^6+1
1475 //10100 = x^5+x^3+1
1476 //110 = x^3+x^2+1
1477 uint8_t seed = 0x12; // Any non zero state
1478 uint8_t lfsr = seed;
1479
1480 if ( m_bitrate == 0 )
1481 return bitSequence;
1482
1483 double period = 1/m_bitrate;
1484 double t = 0;
1485
1486 wxASSERT( m_bits > 0 );
1487
1488 int bits = 0;
1489 do
1490 {
1491 uint8_t lsb = lfsr & 0x01;
1492 bitSequence.emplace_back( ( static_cast<uint8_t>( inverted ) ^ lsb ? 1 : 0 ), t );
1493 lfsr = lfsr >> 1;
1494
1495 if ( lsb )
1496 lfsr ^= polynomial;
1497
1498 t += period;
1499
1500 } while ( ++bits < m_bits );
1501
1502 return bitSequence;
1503}
1504
1506 const IbisWaveform* aFallingWf ) const
1507{
1508 bool status = true;
1509
1510 if( m_cycles < 1 )
1511 {
1512 status = false;
1513 Report( _( "Number of cycles should be greater than 0." ), RPT_SEVERITY_ERROR );
1514 }
1515
1516 if( m_ton <= 0 )
1517 {
1518 status = false;
1519 Report( _( "ON time should be greater than 0." ), RPT_SEVERITY_ERROR );
1520 }
1521
1522 if( m_toff <= 0 )
1523 {
1524 status = false;
1525 Report( _( "OFF time should be greater than 0." ), RPT_SEVERITY_ERROR );
1526 }
1527
1528 if( aRisingWf )
1529 {
1530 if( m_ton < aRisingWf->m_table.m_entries.back().t )
1531 {
1532 status = false;
1533 Report( _( "Rising edge is longer than on time." ), RPT_SEVERITY_WARNING );
1534 }
1535 }
1536
1537 if( aFallingWf )
1538 {
1539 if( m_toff < aFallingWf->m_table.m_entries.back().t )
1540 {
1541 status = false;
1542 Report( _( "Falling edge is longer than off time." ), RPT_SEVERITY_WARNING );
1543 }
1544 }
1545
1546 status &= aRisingWf && aFallingWf;
1547
1548 return status;
1549}
1550
1551
1553 const dvdtTypMinMax& aFallingRp ) const
1554{
1555 bool status = true;
1556
1557 if( m_cycles < 1 )
1558 {
1559 status = false;
1560 Report( _( "Number of cycles should be greater than 0." ), RPT_SEVERITY_ERROR );
1561 }
1562
1563 if( m_ton <= 0 )
1564 {
1565 status = false;
1566 Report( _( "ON time should be greater than 0." ), RPT_SEVERITY_ERROR );
1567 }
1568
1569 if( m_toff <= 0 )
1570 {
1571 status = false;
1572 Report( _( "OFF time should be greater than 0." ), RPT_SEVERITY_ERROR );
1573 }
1574
1575 if( ( m_ton < aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 )
1576 || ( m_ton < aRisingRp.value[IBIS_CORNER::MIN].m_dt / 0.6 )
1577 || ( m_ton < aRisingRp.value[IBIS_CORNER::MAX].m_dt / 0.6 ) )
1578 {
1579 status = false;
1580 Report( _( "Rising edge is longer than ON time." ), RPT_SEVERITY_ERROR );
1581 }
1582
1583 if( ( m_toff < aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 )
1584 || ( m_toff < aFallingRp.value[IBIS_CORNER::MIN].m_dt / 0.6 )
1585 || ( m_toff < aFallingRp.value[IBIS_CORNER::MAX].m_dt / 0.6 ) )
1586 {
1587 status = false;
1588 Report( _( "Falling edge is longer than OFF time." ), RPT_SEVERITY_ERROR );
1589 }
1590
1591 return status;
1592}
1593
1594
1596 const dvdtTypMinMax& aFallingRp ) const
1597{
1598 bool status = true;
1599
1600 if( m_bitrate <= 0 )
1601 {
1602 status = false;
1603 Report( _( "Bitrate should be greater than 0." ), RPT_SEVERITY_ERROR );
1604 }
1605
1606 if( m_bits <= 0 )
1607 {
1608 status = false;
1609 Report( _( "Number of bits should be greater than 0." ), RPT_SEVERITY_ERROR );
1610 }
1611
1612 if( m_bitrate
1613 && ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
1614 + aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) )
1615 && ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
1616 + aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) )
1617 && ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
1618 + aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) ) )
1619 {
1620 status = false;
1621 Report( _( "Bitrate is too high for rising / falling edges" ), RPT_SEVERITY_ERROR );
1622 }
1623
1624 return status;
1625}
1626
1628 const IbisWaveform* aFallingWf ) const
1629{
1630 bool status = true;
1631
1632 if( m_bitrate <= 0 )
1633 {
1634 status = false;
1635 Report( _( "Bitrate should be greater than 0." ), RPT_SEVERITY_ERROR );
1636 }
1637
1638 if( m_bits <= 0 )
1639 {
1640 status = false;
1641 Report( _( "Number of bits should be greater than 0." ), RPT_SEVERITY_ERROR );
1642 }
1643
1644 if( m_bitrate && aRisingWf && aFallingWf
1645 && ( ( 1 / m_bitrate ) < ( aRisingWf->m_table.m_entries.back().t
1646 + aFallingWf->m_table.m_entries.back().t ) ) )
1647 {
1648 status = false;
1649 Report( _( "Bitrate could be too high for rising / falling edges" ), RPT_SEVERITY_WARNING );
1650 }
1651
1652 return status;
1653}
REPORTER * m_reporter
Definition: ibis_parser.h:56
void Report(std::string aMsg, SEVERITY aSeverity=RPT_SEVERITY_INFO) const
Print a message.
Definition: ibis_parser.h:65
static std::string doubleToString(double aNumber)
Convert a double to string using scientific notation.
std::vector< IVtableEntry > m_entries
Definition: ibis_parser.h:359
std::string Spice(int aN, const std::string &aPort1, const std::string &aPort2, const std::string &aModelName, IBIS_CORNER aCorner) const
Interpolate the IV table.
TypMinMaxValue m_Cpkg
Definition: ibis_parser.h:203
TypMinMaxValue m_Lpkg
Definition: ibis_parser.h:202
TypMinMaxValue m_Rpkg
Definition: ibis_parser.h:201
std::string m_signalName
Definition: ibis_parser.h:220
std::string m_pinName
Definition: ibis_parser.h:219
std::string m_modelName
Definition: ibis_parser.h:221
std::string m_manufacturer
Definition: ibis_parser.h:298
IbisComponentPackage m_package
Definition: ibis_parser.h:299
IbisDiffPin m_diffPin
Definition: ibis_parser.h:305
std::string m_name
Definition: ibis_parser.h:297
std::vector< IbisComponentPin > m_pins
Definition: ibis_parser.h:300
std::string pinB
Definition: ibis_parser.h:269
std::string pinA
Definition: ibis_parser.h:268
std::vector< IbisDiffPinEntry > m_entries
Definition: ibis_parser.h:282
std::vector< IbisComponent > m_components
Definition: ibis_parser.h:615
IbisHeader m_header
Definition: ibis_parser.h:614
std::vector< IbisModel > m_models
Definition: ibis_parser.h:617
std::vector< IbisModelSelector > m_modelSelectors
Definition: ibis_parser.h:616
std::string m_fileName
Definition: ibis_parser.h:170
std::string m_copyright
Definition: ibis_parser.h:175
std::string m_notes
Definition: ibis_parser.h:173
double m_ibisVersion
Definition: ibis_parser.h:168
std::string m_date
Definition: ibis_parser.h:172
double m_fileRevision
Definition: ibis_parser.h:169
std::string m_disclaimer
Definition: ibis_parser.h:174
std::string m_modelName
Definition: ibis_parser.h:314
std::string m_modelDescription
Definition: ibis_parser.h:315
std::string m_name
Definition: ibis_parser.h:329
std::vector< IbisModelSelectorEntry > m_models
Definition: ibis_parser.h:330
IBIS_MODEL_TYPE m_type
Definition: ibis_parser.h:543
double m_cref
Definition: ibis_parser.h:550
IVtable m_pullup
Definition: ibis_parser.h:569
TypMinMaxValue m_Cac
Definition: ibis_parser.h:566
TypMinMaxValue m_pullupReference
Definition: ibis_parser.h:559
double m_vmeas
Definition: ibis_parser.h:551
IVtable m_pulldown
Definition: ibis_parser.h:570
TypMinMaxValue m_Rac
Definition: ibis_parser.h:565
std::vector< IbisWaveform * > m_risingWaveforms
Definition: ibis_parser.h:571
IVtable m_POWERClamp
Definition: ibis_parser.h:568
TypMinMaxValue m_Rgnd
Definition: ibis_parser.h:563
TypMinMaxValue m_POWERClampReference
Definition: ibis_parser.h:562
IVtable m_GNDClamp
Definition: ibis_parser.h:567
IbisRamp m_ramp
Definition: ibis_parser.h:573
IBIS_MODEL_POLARITY m_polarity
Definition: ibis_parser.h:553
TypMinMaxValue m_C_comp
Definition: ibis_parser.h:556
double m_rref
Definition: ibis_parser.h:549
IBIS_MODEL_ENABLE m_enable
Definition: ibis_parser.h:552
TypMinMaxValue m_temperatureRange
Definition: ibis_parser.h:558
std::vector< IbisWaveform * > m_fallingWaveforms
Definition: ibis_parser.h:572
TypMinMaxValue m_pulldownReference
Definition: ibis_parser.h:560
double m_vref
Definition: ibis_parser.h:548
TypMinMaxValue m_GNDClampReference
Definition: ibis_parser.h:561
double m_vinh
Definition: ibis_parser.h:547
double m_vinl
Definition: ibis_parser.h:546
TypMinMaxValue m_voltageRange
Definition: ibis_parser.h:557
TypMinMaxValue m_Rpower
Definition: ibis_parser.h:564
std::string m_name
Definition: ibis_parser.h:542
bool ParseFile(const std::string &aFileName)
Parse a file.
bool m_parrot
Definition: ibis_parser.h:658
IbisFile m_ibisFile
Definition: ibis_parser.h:668
dvdtTypMinMax m_rising
Definition: ibis_parser.h:479
dvdtTypMinMax m_falling
Definition: ibis_parser.h:478
double m_L_fixture
Definition: ibis_parser.h:503
double m_V_fixture
Definition: ibis_parser.h:504
VTtable m_table
Definition: ibis_parser.h:496
double m_V_fixture_min
Definition: ibis_parser.h:505
double m_V_fixture_max
Definition: ibis_parser.h:506
double m_R_fixture
Definition: ibis_parser.h:501
double m_C_fixture
Definition: ibis_parser.h:502
KIBIS_ANY(KIBIS *aTopLevel)
Definition: kibis.cpp:68
bool m_valid
Definition: kibis.h:57
KIBIS * m_topLevel
Definition: kibis.h:56
KIBIS_COMPONENT(KIBIS &aToplevel, const IbisComponent &aSource, IbisParser &aParser)
Definition: kibis.cpp:302
std::vector< KIBIS_PIN > m_pins
Definition: kibis.h:441
std::string m_manufacturer
Name of the manufacturer.
Definition: kibis.h:439
std::string m_name
Name of the component.
Definition: kibis.h:437
KIBIS_PIN * GetPin(const std::string &aPinNumber)
Get a pin by its number ( 1, 2, A1, A2, ... )
Definition: kibis.cpp:327
KIBIS_FILE(KIBIS &aTopLevel)
Definition: kibis.cpp:137
std::string m_notes
Definition: kibis.h:223
double m_ibisVersion
Definition: kibis.h:220
std::string m_date
Definition: kibis.h:221
bool Init(const IbisParser &aParser)
Definition: kibis.cpp:144
std::string m_fileName
Definition: kibis.h:218
std::string m_copyright
Definition: kibis.h:225
std::string m_disclaimer
Definition: kibis.h:224
double m_fileRev
Definition: kibis.h:219
std::vector< IbisWaveform * > m_fallingWaveforms
Definition: kibis.h:266
IbisWaveform TrimWaveform(const IbisWaveform &aIn) const
Copy a waveform, and substract the first value to all samples.
Definition: kibis.cpp:440
IBIS_MODEL_ENABLE m_enable
Definition: kibis.h:246
double m_vref
Definition: kibis.h:242
std::string m_name
Definition: kibis.h:235
bool HasPOWERClamp() const
Return true if the model has a clamp diode to the power net.
Definition: kibis.cpp:496
double m_vmeas
Definition: kibis.h:245
std::vector< IbisWaveform * > m_risingWaveforms
Definition: kibis.h:265
TypMinMaxValue m_Cac
Definition: kibis.h:260
double m_vinh
Definition: kibis.h:241
double m_rref
Definition: kibis.h:243
bool HasPullup() const
Return true if the model has a pullup transistor.
Definition: kibis.cpp:484
bool HasGNDClamp() const
Return true if the model has a clamp diode to the gnd net.
Definition: kibis.cpp:490
TypMinMaxValue m_pulldownReference
Definition: kibis.h:254
TypMinMaxValue m_GNDClampReference
Definition: kibis.h:255
TypMinMaxValue m_Rpower
Definition: kibis.h:258
bool HasPulldown() const
Return true if the model has a pulldown transistor.
Definition: kibis.cpp:478
IBIS_MODEL_TYPE m_type
Definition: kibis.h:237
IbisRamp m_ramp
Definition: kibis.h:267
IVtable m_pullup
Definition: kibis.h:263
IBIS_MODEL_POLARITY m_polarity
Definition: kibis.h:247
double m_cref
Definition: kibis.h:244
std::string generateSquareWave(const std::string &aNode1, const std::string &aNode2, const std::vector< std::pair< int, double > > &aBits, const std::pair< IbisWaveform *, IbisWaveform * > &aPair, const KIBIS_PARAMETER &aParam)
Generate a square waveform.
Definition: kibis.cpp:502
TypMinMaxValue m_Rac
Definition: kibis.h:259
TypMinMaxValue m_temperatureRange
Definition: kibis.h:252
TypMinMaxValue m_voltageRange
Definition: kibis.h:251
IVtable m_GNDClamp
Definition: kibis.h:261
TypMinMaxValue m_Rgnd
Definition: kibis.h:257
std::string m_description
Definition: kibis.h:236
KIBIS_MODEL(KIBIS &aTopLevel, const IbisModel &aSource, IbisParser &aParser)
Definition: kibis.cpp:238
IVtable m_POWERClamp
Definition: kibis.h:262
TypMinMaxValue m_pullupReference
Definition: kibis.h:253
std::vector< std::pair< IbisWaveform *, IbisWaveform * > > waveformPairs()
Create waveform pairs.
Definition: kibis.cpp:340
TypMinMaxValue m_POWERClampReference
Definition: kibis.h:256
TypMinMaxValue m_C_comp
Definition: kibis.h:250
std::string SpiceDie(const KIBIS_PARAMETER &aParam, int aIndex) const
Generate the spice directive to simulate the die.
Definition: kibis.cpp:367
IVtable m_pulldown
Definition: kibis.h:264
double m_vinl
Definition: kibis.h:240
IBIS_CORNER m_supply
Definition: kibis.h:205
IBIS_CORNER m_Cpin
Definition: kibis.h:203
KIBIS_ACCURACY m_accuracy
Definition: kibis.h:207
IBIS_CORNER m_Ccomp
Definition: kibis.h:204
IBIS_CORNER m_Lpin
Definition: kibis.h:202
IBIS_CORNER m_Rpin
Definition: kibis.h:201
void SetCornerFromString(IBIS_CORNER &aCorner, const std::string &aString)
Definition: kibis.cpp:1415
KIBIS_WAVEFORM * m_waveform
Definition: kibis.h:206
TypMinMaxValue m_Rpin
Resistance from die to pin.
Definition: kibis.h:340
bool writeSpiceDiffDriver(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1298
TypMinMaxValue m_Lpin
Inductance from die to pin.
Definition: kibis.h:342
void getKuKdFromFile(const std::string &aSimul)
Update m_Ku, m_Kd using with two waveform inputs.
Definition: kibis.cpp:658
KIBIS_COMPONENT * m_parent
Definition: kibis.h:346
std::vector< double > m_Ku
Definition: kibis.h:348
std::string m_pinNumber
Pin Number Examples : 1, 2, 3 ( or for BGA ), A1, A2, A3, etc...
Definition: kibis.h:337
std::string addDie(KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam, int aIndex)
Generate the spice directive to simulate the die for Ku/Kd estimation.
Definition: kibis.cpp:606
bool writeSpiceDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1247
std::vector< KIBIS_MODEL * > m_models
Definition: kibis.h:350
std::vector< double > m_t
Definition: kibis.h:348
TypMinMaxValue m_Cpin
Capacitance from pin to GND.
Definition: kibis.h:344
std::string m_signalName
Name of the pin Examples : "VCC", "GPIOA", "CLK", etc...
Definition: kibis.h:333
void getKuKdTwoWaveforms(KIBIS_MODEL &aModel, const std::pair< IbisWaveform *, IbisWaveform * > &aPair1, const std::pair< IbisWaveform *, IbisWaveform * > &aPair2, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using with two waveform inputs.
Definition: kibis.cpp:983
void getKuKdOneWaveform(KIBIS_MODEL &aModel, const std::pair< IbisWaveform *, IbisWaveform * > &aPair, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using with a single waveform input.
Definition: kibis.cpp:812
bool writeSpiceDiffDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1349
std::string KuKdDriver(KIBIS_MODEL &aModel, const std::pair< IbisWaveform *, IbisWaveform * > &aPair, const KIBIS_PARAMETER &aParam, int aIndex)
Update m_Ku, m_Kd using with two waveform inputs.
Definition: kibis.cpp:738
KIBIS_PIN(KIBIS &aTopLevel, const IbisComponentPin &aPin, const IbisComponentPackage &aPackage, IbisParser &aParser, KIBIS_COMPONENT *aParent, std::vector< KIBIS_MODEL > &aModels)
Definition: kibis.cpp:161
std::vector< double > m_Kd
Definition: kibis.h:348
bool writeSpiceDriver(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1125
KIBIS_PIN * m_complementaryPin
Definition: kibis.h:427
void getKuKdNoWaveform(KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using no falling / rising waveform inputs ( low accuracy )
Definition: kibis.cpp:921
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1445
bool Check(const IbisWaveform *aRisingWf, const IbisWaveform *aFallingWf) const override
Definition: kibis.cpp:1627
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1470
double m_bitrate
Definition: kibis.h:129
bool Check(const IbisWaveform *aRisingWf, const IbisWaveform *aFallingWf) const override
Definition: kibis.cpp:1505
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1451
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1426
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1436
virtual bool Check(const IbisWaveform *aRisingWf, const IbisWaveform *aFallingWf) const
Definition: kibis.h:87
KIBIS_WAVEFORM_TYPE GetType() const
Definition: kibis.h:75
bool inverted
Definition: kibis.h:77
virtual double GetDuration() const
Definition: kibis.h:76
virtual std::vector< std::pair< int, double > > GenerateBitSequence() const
Definition: kibis.h:80
Definition: kibis.h:452
std::vector< KIBIS_MODEL > m_models
Definition: kibis.h:460
KIBIS()
Constructor for unitialized KIBIS members.
Definition: kibis.h:455
std::vector< KIBIS_COMPONENT > m_components
Definition: kibis.h:459
KIBIS_MODEL * GetModel(const std::string &aName)
Return the model with name aName .
Definition: kibis.cpp:1393
KIBIS_COMPONENT * GetComponent(const std::string &aName)
Return the component with name aName .
Definition: kibis.cpp:1404
KIBIS_FILE m_file
Definition: kibis.h:461
std::string m_cacheDir
Absolute path of the directory that will be used for caching.
Definition: kibis.h:464
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:72
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
double value[3]
Definition: ibis_parser.h:185
TypMinMaxValue V
Definition: ibis_parser.h:403
std::vector< VTtableEntry > m_entries
Definition: ibis_parser.h:413
dvdt value[3]
Definition: ibis_parser.h:463
double m_dt
Definition: ibis_parser.h:456
#define _(s)
IBIS_CORNER
Definition: ibis_parser.h:94
@ TYP
Definition: ibis_parser.h:95
@ MIN
Definition: ibis_parser.h:96
@ MAX
Definition: ibis_parser.h:97
std::vector< std::pair< int, double > > SimplifyBitSequence(const std::vector< std::pair< int, double > > &bits)
Definition: kibis.cpp:51
IBIS_CORNER ReverseLogic(IBIS_CORNER aIn)
Definition: kibis.cpp:77
KIBIS_ACCURACY
Accuracy level.
Definition: kibis.h:191
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
constexpr int delta
#define ku