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