KiCad PCB EDA Suite
ibis_parser.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 *
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
17 * to endorse or promote products derived from this software without specific
18 * prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32#include "ibis_parser.h"
33
34#include <sstream>
35#include <cstring> //for memcmp
36#include <iterator>
37#include <locale_io.h> // KiCad header
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
50bool IbisParser::compareIbisWord( const std::string& stra, const std::string& strb )
51{
52 return std::equal( stra.begin(), stra.end(),
53 strb.begin(), strb.end(),
54 [](char a, char b)
55 {
56 return std::tolower(a) == std::tolower(b);
57 });
58}
59
61{
62 bool status = true;
63
64 if( m_dim < 1 )
65 {
66 Report( _( "Dimension of matrices should be >= 1." ), RPT_SEVERITY_ERROR );
67 status = false;
68 }
69
70 if( m_bandwidth < 1 )
71 {
72 Report( _( "Bandwidth of banded matrices should be >= 1." ), RPT_SEVERITY_ERROR );
73 status = false;
74 }
75
76 for( int i = 0; i < m_bandwidth * m_dim; i++ )
77 {
78 if( isnan( m_data[i] ) )
79 {
80 Report( _( "There are NaN elements in a matrix." ), RPT_SEVERITY_ERROR );
81 status = false;
82 }
83 }
84
85
86 return status;
87}
88
90{
91 bool status = true;
92
93 if( m_dim < 1 )
94 {
95 Report( _( "Dimension of matrices should be >= 1." ), RPT_SEVERITY_ERROR );
96 status = false;
97 }
98
99 for( int i = 0; i < m_dim * m_dim; i++ )
100 {
101 if( isnan( m_data[i] ) )
102 {
103 Report( _( "There are NaN elements in a matrix." ), RPT_SEVERITY_ERROR );
104 status = false;
105 }
106 }
107
108
109 return status;
110}
111
113{
114 bool status = true;
115
116 if( m_dim < 1 )
117 {
118 Report( _( "Dimension of matrices should be >= 1." ), RPT_SEVERITY_ERROR );
119 status = false;
120 }
121
122 for( int i = 0; i < m_dim * m_dim; i++ )
123 {
124 if( isnan( m_data[i] ) )
125 {
126 Report( _( "There are NaN elements in a matrix." ), RPT_SEVERITY_ERROR );
127 status = false;
128 }
129 }
130
131
132 return status;
133}
134
135bool isNumberNA( double aNumber )
136{
137 double NA = nan( NAN_NA );
138 return std::memcmp( &aNumber, &NA, sizeof NA ) == 0;
139}
140
142{
143 bool status = true;
144
145 if( isnan( value[IBIS_CORNER::TYP] ) )
146 status = false;
148 status = false;
150 status = false;
151
152 return status;
153}
154
156{
157 bool status = true;
158
159 if( !m_Rpkg.Check() )
160 {
161 Report( _( "Invalid R_pkg value." ), RPT_SEVERITY_ERROR );
162 status = false;
163 }
164 if( !m_Lpkg.Check() )
165 {
166 Report( _( "Invalid L_pkg value." ), RPT_SEVERITY_ERROR );
167 status = false;
168 }
169 if( !m_Cpkg.Check() )
170 {
171 Report( _( "Invalid C_pkg value." ), RPT_SEVERITY_ERROR );
172 status = false;
173 }
174
175 return status;
176}
177
179{
180 bool status = true;
181
182 if( !m_dummy )
183 {
184 std::stringstream message;
185 message << _( "Checking pin " ) << m_pinName;
186 Report( message.str(), RPT_SEVERITY_ACTION );
187
188 if( m_pinName.empty() )
189 {
190 Report( _( "Pin name cannot be empty." ), RPT_SEVERITY_ERROR );
191 status = false;
192 }
193 if( m_signalName.empty() )
194 {
195 Report( _( "Signal name cannot be empty." ), RPT_SEVERITY_ERROR );
196 status = false;
197 }
198 if( m_modelName.empty() )
199 {
200 Report( _( "Model name cannot be empty." ), RPT_SEVERITY_ERROR );
201 status = false;
202 }
203 if( isnan( m_Rpin ) && !isNumberNA( m_Rpin ) )
204 {
205 Report( _( "Rpin is not valid." ), RPT_SEVERITY_ERROR );
206 status = false;
207 }
208 if( isnan( m_Lpin )&& !isNumberNA( m_Lpin ) )
209 {
210 Report( _( "Lpin is not valid." ), RPT_SEVERITY_ERROR );
211 status = false;
212 }
213 if( isnan( m_Cpin )&& !isNumberNA( m_Cpin ) )
214 {
215 Report( _( "Cpin is not valid." ), RPT_SEVERITY_ERROR );
216 status = false;
217 }
218 }
219 return status;
220}
221
222
224{
225 bool status = true;
226
227 if( m_name.empty() )
228 {
229 Report( _( "Component name cannot be empty." ), RPT_SEVERITY_ERROR );
230 status = false;
231 }
232
233 std::stringstream message;
234 message << _( "Checking component " ) << m_name;
235 Report( message.str(), RPT_SEVERITY_ACTION );
236
237 if( m_manufacturer.empty() )
238 {
239 Report( _( "Component: manufacturer cannot be empty." ), RPT_SEVERITY_ERROR );
240 status = false;
241 }
242
243 if( !m_package.Check() )
244 {
245 Report( _( "Component: Invalid Package." ), RPT_SEVERITY_ERROR );
246 status = false;
247 }
248
249 if( m_pins.size() < 1 )
250 {
251 Report( _( "Component: no pin" ), RPT_SEVERITY_ERROR );
252 status = false;
253 }
254
255 for( IbisComponentPin& pin : m_pins )
256 {
257 status &= pin.Check();
258 }
259
260 return status;
261}
262
263
265{
266 return true;
267}
268
269
270std::string IBIS_ANY::doubleToString( double aNumber )
271{
272 std::ostringstream ss;
273 ss.setf( std::ios_base::scientific, std::ios_base::floatfield );
274 ss << aNumber;
275 return ss.str();
276}
277
278
279std::string IVtable::Spice( int aN, std::string aPort1, std::string aPort2, std::string aModelName,
280 IBIS_CORNER aCorner )
281{
282 std::string result = "";
283
284 if( m_entries.size() > 0 )
285 {
286 result += "a";
287 result += std::to_string( aN );
288 result += " %vd(";
289 result += aPort1;
290 result += " ";
291 result += aPort2;
292 result += ") %id(";
293 result += aPort1;
294 result += " ";
295 result += aPort2;
296 result += ") ";
297 result += aModelName;
298 result += "\n";
299 result += "\n";
300 result += ".model ";
301 result += aModelName;
302 result += " pwl(\n+ x_array=[";
303
304 for( IVtableEntry& entry : m_entries )
305 {
306 result += doubleToString( entry.V );
307 result += "\n+";
308 }
309 result += "]\n+ y_array=[";
310
311 for( IVtableEntry& entry : m_entries )
312 {
313 result += doubleToString( entry.I.value[aCorner] );
314 result += "\n+";
315 }
316 result += "]\n+ input_domain=0.05 fraction=TRUE)\n\n";
317 }
318 return result;
319}
320
321double IVtable::InterpolatedI( double aV, IBIS_CORNER aCorner )
322{
323 // @TODO change this algorithm
324
325 if( m_entries.back().V > m_entries.at( 0 ).V )
326 {
327 if( aV >= m_entries.back().V )
328 {
329 return m_entries.back().I.value[aCorner];
330 }
331
332 if( aV <= m_entries.at( 0 ).V )
333 {
334 return m_entries.at( 0 ).I.value[aCorner];
335 }
336
337 for( size_t i = 1; i < m_entries.size(); i++ )
338 {
339 if( m_entries.at( i ).V > aV )
340 {
341 return m_entries.at( i - 1 ).I.value[aCorner]
342 + ( m_entries.at( i ).I.value[aCorner]
343 - m_entries.at( i - 1 ).I.value[aCorner] )
344 / ( m_entries.at( i ).V - m_entries.at( i - 1 ).V )
345 * ( aV - m_entries.at( i - 1 ).V );
346 }
347 }
348 Report( _( "Cannot interpolate the current based on this IV table." ), RPT_SEVERITY_ERROR );
349 return nan( "" );
350 }
351 else
352 {
353 // exiting the function here would mean the IV table is reversed.
354 return nan( "" );
355 }
356 // @TODO prefer another method such as a dichotomy
357}
358
360{
361 bool status = true;
362 for( IVtableEntry& entry : m_entries )
363 {
364 if( isnan( entry.V ) )
365 {
366 Report( _( "There is a Nan voltage in an IV table" ), RPT_SEVERITY_ERROR );
367 status = false;
368 break;
369 }
370
371 if( !entry.I.Check() )
372 {
373 Report( _( "There is an invalid current in an IV table" ), RPT_SEVERITY_ERROR );
374 status = false;
375 break;
376 }
377 }
378 // TODO: Check if the IV table is monotonic :
379 // IBIS standard defines 8 criteria for an IV table to be monotonic
380 // Issue a warning, not an error
381
382 return status;
383}
384
385
387{
388 bool status = true;
389
390 if( isnan( value[IBIS_CORNER::TYP].m_dv ) )
391 status = false;
392 if( isnan( value[IBIS_CORNER::TYP].m_dt ) )
393 status = false;
394
395
396 if( isnan( value[IBIS_CORNER::MIN].m_dv ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dv ) )
397 status = false;
398 if( isnan( value[IBIS_CORNER::MIN].m_dt ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dt ) )
399 status = false;
400
401 if( isnan( value[IBIS_CORNER::MIN].m_dv ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dv ) )
402 status = false;
403 if( isnan( value[IBIS_CORNER::MIN].m_dt ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dt ) )
404 status = false;
405
406 return status;
407}
408
410{
411 bool status = true;
412
413 if( isnan( m_Rload ) )
414 {
415 status = false;
416 Report( _( "Invalid R_load." ), RPT_SEVERITY_ERROR );
417 }
418 if( !m_falling.Check() )
419 {
420 Report( _( "Invalid falling dv/dt." ), RPT_SEVERITY_ERROR );
421 status = false;
422 }
423 if( !m_rising.Check() )
424 {
425 Report( _( "Invalid rising dv/dt." ), RPT_SEVERITY_ERROR );
426 status = false;
427 }
428
429 return status;
430}
431
432
433
435{
436 bool status = true;
437
438 if( m_name.empty() )
439 {
440 Report( _( "Model name cannot be empty" ), RPT_SEVERITY_ERROR );
441 status = false;
442 }
443
444 std::stringstream message;
445 message << _( "Checking model " ) << m_name;
446 Report( message.str(), RPT_SEVERITY_ACTION );
447
449 {
450 Report( _( "Undefined model type" ), RPT_SEVERITY_ERROR );
451 status = false;
452 }
453
454 if( isnan( m_vinh ) && !isNumberNA( m_vinh ) )
455 {
456 Report( _( "Invalid Vinh value." ), RPT_SEVERITY_ERROR );
457 status = false;
458 }
459 if( isnan( m_vinl ) && !isNumberNA( m_vinl ) )
460 {
461 Report( _( "Invalid Vinl value." ), RPT_SEVERITY_ERROR );
462 status = false;
463 }
464 if( isnan( m_rref ) && !isNumberNA( m_rref ) )
465 {
466 Report( _( "Invalid R_ref value." ), RPT_SEVERITY_ERROR );
467 status = false;
468 }
469 if( isnan( m_cref ) && !isNumberNA( m_cref ) )
470 {
471 Report( _( "Invalid C_ref value." ), RPT_SEVERITY_ERROR );
472 status = false;
473 }
474 if( isnan( m_vref ) && !isNumberNA( m_vref ) )
475 {
476 Report( _( "invalid V_ref value." ), RPT_SEVERITY_ERROR );
477 status = false;
478 }
479 if( isnan( m_vmeas ) && !isNumberNA( m_vmeas ) )
480 {
481 Report( _( "Invalid V_meas value." ), RPT_SEVERITY_ERROR );
482 status = false;
483 }
484 if( !m_C_comp.Check() )
485 {
486 Report( _( "C_comp is invalid." ), RPT_SEVERITY_ERROR );
487 status = false;
488 }
490 {
491 Report( _( "Temperature Range is invalid." ), RPT_SEVERITY_ERROR );
492 status = false;
493 }
494
495 if( !m_voltageRange.Check() )
496 {
497 // If the voltage range is not valid, it's ok, only if we have pulls and clamps
499 {
500 status = false;
501 }
502 if( !m_pullupReference.Check() )
503 {
504 status = false;
505 }
507 {
508 status = false;
509 }
511 {
512 status = false;
513 }
514 if( !status )
515 {
516 Report( _( "Voltage Range is invalid." ), RPT_SEVERITY_ERROR );
517 }
518 status = false;
519 }
520 if( !m_pulldown.Check() )
521 {
522 Report( _( "Invalid pulldown." ), RPT_SEVERITY_ERROR );
523 status = false;
524 }
525 if( !m_pullup.Check() )
526 {
527 Report( _( "Invalid pullup." ), RPT_SEVERITY_ERROR );
528 status = false;
529 }
530 if( !m_POWERClamp.Check() )
531 {
532 Report( _( "Invalid POWER clamp." ), RPT_SEVERITY_ERROR );
533 status = false;
534 }
535 if( !m_GNDClamp.Check() )
536 {
537 Report( _( "Invalid GND clamp." ), RPT_SEVERITY_ERROR );
538 status = false;
539 }
543 {
544 if( !m_ramp.Check() )
545 {
546 Report( _( "Invalid Ramp" ), RPT_SEVERITY_ERROR );
547 }
548 }
549 return status;
550}
551
553{
554 bool status = true;
555
556 Report( _( "Checking Header..." ), RPT_SEVERITY_ACTION );
557
558 if( m_ibisVersion == -1 )
559 {
560 Report( _( "Missing [IBIS Ver]" ), RPT_SEVERITY_ERROR );
561 status = false;
562 }
563
565 {
566 Report( _( "The parser does not handle this IBIS version" ), RPT_SEVERITY_ERROR );
567 status = false;
568 }
569
570 if( m_fileRevision == -1 )
571 {
572 Report( _( "Missing [File Rev]" ), RPT_SEVERITY_ERROR );
573 status = false;
574 }
575
576 if( m_fileName.empty() )
577 {
578 Report( _( "Missing [File Name]" ), RPT_SEVERITY_ERROR );
579 status = false;
580 }
581
582 std::string ext = m_fileName.substr( m_fileName.length() - 4 );
583
584 if( !( !strcmp( ext.c_str(), ".ibs" ) || !strcmp( ext.c_str(), ".pkg" )
585 || !strcmp( ext.c_str(), ".ebd" ) || !strcmp( ext.c_str(), ".ims" ) ) )
586 {
587 Report( "Invalid file extension in [File Name]", RPT_SEVERITY_ERROR );
588 status = false;
589 }
590
591
592 return status;
593}
594
596{
597 bool status = true;
598
599 if( m_name.empty() )
600 {
601 Report( _( "Package model name cannot be empty." ), RPT_SEVERITY_ERROR );
602 status = false;
603 }
604
605 std::stringstream message;
606 message << _( "Checking package model " ) << m_name;
607 Report( message.str(), RPT_SEVERITY_ACTION );
608
609 if( m_manufacturer.empty() )
610 {
611 Report( _( "Manufacturer cannot be empty." ), RPT_SEVERITY_ERROR );
612 status = false;
613 }
614
615 if( m_OEM.empty() )
616 {
617 Report( _( "OEM cannot be empty." ), RPT_SEVERITY_ERROR );
618 status = false;
619 }
620
621 if( m_numberOfPins < 0 )
622 {
623 Report( _( "Negative number of pins." ), RPT_SEVERITY_ERROR );
624 status = false;
625 }
626
627 if( (int)m_pins.size() != m_numberOfPins )
628 {
629 Report( "Number of pins does not match [Pin Numbers] size", RPT_SEVERITY_ERROR );
630 status = false;
631 }
632
633 for( size_t i = 0; i < m_pins.size(); i++ )
634 {
635 if( m_pins.at( i ).empty() )
636 {
637 Report( _( "Empty pin number" ), RPT_SEVERITY_ERROR );
638 status = false;
639 }
640 }
641 // resistance matrix is not required
642
643 if( !( m_resistanceMatrix )->Check() )
644 {
645 Report( _( "Resistance matrix is incorrect" ), RPT_SEVERITY_ERROR );
646 status = false;
647 }
648
649 if( m_capacitanceMatrix != nullptr )
650 {
652 {
653 Report( _( "Capacitance matrix is undefined" ), RPT_SEVERITY_ERROR );
654 status = false;
655 }
656
657 if( !m_capacitanceMatrix->Check() )
658 {
659 Report( _( "Capacitance matrix is incorrect" ), RPT_SEVERITY_ERROR );
660 status = false;
661 }
662 }
663 else
664 {
665 Report( _( "Capacitance matrix is nullptr" ), RPT_SEVERITY_ERROR );
666 status = false;
667 }
668
669 if( m_inductanceMatrix != nullptr )
670 {
672 {
673 Report( _( "Inductance matrix is undefined" ), RPT_SEVERITY_ERROR );
674 status = false;
675 }
676
677 if( !m_inductanceMatrix->Check() )
678 {
679 Report( _( "Inductance matrix is incorrect" ), RPT_SEVERITY_ERROR );
680 status = false;
681 }
682 }
683 else
684 {
685 Report( _( "Inductance matrix is nullptr" ), RPT_SEVERITY_ERROR );
686 status = false;
687 }
688 return status;
689}
690
691
692bool IbisParser::ParseFile( std::string& aFileName )
693{
694 std::stringstream err_msg;
695
696 std::ifstream ibisFile;
697 ibisFile.open( aFileName );
698
699 if( !ibisFile.is_open() )
700 {
701 err_msg << _( "Cannot open file " ) << aFileName;
702 Report( err_msg.str(), RPT_SEVERITY_ERROR );
703 return false;
704 }
705
706 err_msg.clear();
707 err_msg << _( "Reading file " ) << aFileName << wxT( "..." );
708 Report( err_msg.str(), RPT_SEVERITY_ACTION );
709
710 std::ostringstream ss;
711 ss << ibisFile.rdbuf();
712 const std::string& s = ss.str();
713 m_buffer = std::vector<char>( s.begin(), s.end() );
714 m_buffer.push_back( 0 );
715
716 long size = m_buffer.size();
717
718 m_lineCounter = 0;
719 m_bufferIndex = 0;
720
721 bool status = true;
722
723 LOCALE_IO toggle; // Temporary switch the locale to standard C to r/w floats
724
725 while( ( m_bufferIndex < size ) && status )
726 {
727 if( !getNextLine() )
728 {
729 Report( _( "Unexpected end of file. Missing [END] ?" ), RPT_SEVERITY_ERROR );
730 status = false;
731 }
732
733 if( status && m_parrot )
734 {
735 printLine();
736 }
737
738 if( status && !onNewLine() )
739 {
740 err_msg.clear();
741 err_msg << _( "Error on line " ) << std::to_string( m_lineCounter );
742 Report( err_msg.str(), RPT_SEVERITY_ERROR );
743 status = false;
744 }
746 {
747 break;
748 }
749 }
750
751 m_buffer.clear();
752 return status;
753}
754
756{
757 while( ( isspace( m_buffer[m_lineOffset + m_lineIndex] ) ) && ( m_lineIndex < m_lineLength ) )
758 {
759 m_lineIndex++;
760 }
761}
762
764{
766
768 {
769 Report( _( "A line did not end properly." ), RPT_SEVERITY_ERROR );
770 return false;
771 }
772 return true;
773}
774
775
777{
778 int cursor = m_lineIndex;
779
780 while( ( isspace( m_buffer[m_lineOffset + cursor] ) ) && ( cursor < m_lineLength ) )
781 {
782 cursor++;
783 }
784
785 return ( cursor >= m_lineLength );
786}
787
788bool IbisParser::readDvdt( std::string& aString, dvdt& aDest )
789{
790 bool status = true;
791
792 if( aString == "NA" )
793 {
794 aDest.m_dv = nan( NAN_NA );
795 aDest.m_dt = nan( NAN_NA );
796
797 return status;
798 }
799
800 int i = 0;
801
802 for( i = 1; i < (int)aString.length(); i++ )
803 {
804 if( aString.at( i ) == '/' )
805 {
806 break;
807 }
808 }
809
810 if( aString.at( i ) == '/' )
811 {
812 std::string str1 = aString.substr( 0, i );
813 std::string str2 = aString.substr( i + 1, aString.size() - i - 1 );
814
815 if( !parseDouble( aDest.m_dv, str1, true ) || !parseDouble( aDest.m_dt, str2, true ) )
816 {
817 status = false;
818 }
819 }
820
821 return status;
822}
823
824
825bool IbisParser::parseDouble( double& aDest, std::string& aStr, bool aAllowModifiers )
826{
827 // " an entry of the C matrix could be given as 1.23e-12 or as 1.23p or 1.23pF."
828 // Kibis: This implementation will also allow 1.23e-3n
829
831 bool status = true;
832 bool converted = false;
833
834 std::string str = aStr;
835
836 double result;
837 size_t size = 0;
838
839
840 if( str == "NA" )
841 {
842 result = nan( NAN_NA );
843 }
844 else
845 {
846 try
847 {
848 result = std::stod( str, &size );
849 converted = true;
850 }
851 catch( ... )
852 {
853 result = nan( NAN_INVALID );
854 status = false;
855 }
856 }
857
858 if( converted && ( size < str.length() ) )
859 {
860 switch( static_cast<char>( str.at( size ) ) )
861 {
862 case 'T': result *= 1e12; break;
863 case 'G': result *= 1e9; break;
864 case 'M': result *= 1e6; break;
865 case 'k': result *= 1e3; break;
866 case 'm': result *= 1e-3; break;
867 case 'u': result *= 1e-6; break;
868 case 'n': result *= 1e-9; break;
869 case 'p': result *= 1e-12; break;
870 case 'f': result *= 1e-15; break;
871 default:
872 break;
873 // In some files, "vinh = 3.0V", therefore we can't return false in the default case
874 }
875 }
876
877 aDest = result;
878
879 return status;
880}
881
882
884{
886
887 long tmpIndex = m_bufferIndex;
888
890
891 if( m_bufferIndex >= (int)m_buffer.size() )
892 return false;
893
894 char c = m_buffer[m_bufferIndex++];
895
896 int i = 1;
897 while( c != m_commentChar && c != 0 && c != '\n' && i < IBIS_MAX_LINE_LENGTH )
898 {
899 c = m_buffer[m_bufferIndex++];
900 i++;
901 }
902
903 if( i == IBIS_MAX_LINE_LENGTH )
904 {
905 Report( _( "Line exceeds maximum length." ), RPT_SEVERITY_ERROR );
906 return false;
907 }
908
909 m_lineLength = m_bufferIndex - tmpIndex - 1; // Don't add the end of line condition
910 m_lineIndex = 0;
911
912 if( c == m_commentChar )
913 {
914 while( c != 0 && c != '\n' )
915 {
916 c = m_buffer[m_bufferIndex++];
917 }
918 }
919
920 if( i == IBIS_MAX_LINE_LENGTH )
921 {
922 Report( _( "Line exceeds maximum length." ), RPT_SEVERITY_ERROR );
923 return false;
924 }
925
926 return true;
927}
928
929
931{
932 for( int i = 0; i < m_lineLength; i++ )
933 {
934 std::cout << m_buffer[m_lineOffset + i];
935 }
936 std::cout << std::endl;
937}
938
939bool IbisParser::readDouble( double& aDest )
940{
941 bool status = true;
942 std::string str;
943
944 if( readWord( str ) )
945 {
946 if( !parseDouble( aDest, str, true ) )
947 {
948 Report( _( "Failed to read a double." ), RPT_SEVERITY_WARNING );
949 status = false;
950 }
951 }
952 else
953 {
954 Report( _( "Failed to read a word." ), RPT_SEVERITY_WARNING );
955 status = false;
956 }
957
958 return status;
959}
960
961bool IbisParser::readInt( int& aDest )
962{
963 bool status = true;
964 std::string str;
965
966 if( readWord( str ) )
967 {
968 double result;
969 size_t size = 0;
970
971 try
972 {
973 result = std::stoi( str, &size );
974 }
975 catch( ... )
976 {
977 if( str == "NA" )
978 {
979 result = nan( NAN_NA );
980 }
981 else
982 {
983 result = nan( NAN_INVALID );
984 status = false;
985 }
986 }
987
988 if( size != str.size() )
989 {
990 status = false;
991 Report( _( "Number is not an integer" ), RPT_SEVERITY_WARNING );
992 }
993
994 aDest = result;
995 }
996 else
997 {
998 Report( _( "Failed to read a word." ), RPT_SEVERITY_WARNING );
999 status = false;
1000 }
1001
1002 return status;
1003}
1004
1005bool IbisParser::readWord( std::string& aDest )
1006{
1008
1009 int startIndex = m_lineIndex;
1010
1011 while( ( !isspace( m_buffer[m_lineOffset + m_lineIndex] ) ) && ( m_lineIndex < m_lineLength ) )
1012 {
1013 m_lineIndex++;
1014 }
1015
1016 std::vector<char>::iterator start = std::next( m_buffer.begin(), m_lineOffset + startIndex );
1017 std::vector<char>::iterator end = std::next( m_buffer.begin(), m_lineOffset + m_lineIndex );
1018 aDest = std::string( start, end );
1019
1020 return ( aDest.size() > 0 );
1021}
1022
1023bool IbisParser::readString( std::string& aDest )
1024{
1025 while( m_lineIndex < m_lineLength )
1026 {
1027 aDest += m_buffer[m_lineOffset + m_lineIndex++];
1028 }
1029
1030 // Remove extra whitespace characters
1031 int len = aDest.length();
1032
1033 if( len < 1 )
1034 {
1035 Report( _( "Unable to read string, input is empty." ), RPT_SEVERITY_ERROR );
1036 return false;
1037 }
1038
1039 char c = aDest[len - 1];
1040 int i = 0;
1041
1042 while( isspace( c ) && ( i < len ) )
1043 {
1044 c = aDest[len - 1 - i];
1045 i++;
1046 }
1047 aDest = aDest.substr( 0, len - i + 1 );
1048
1049 return true;
1050}
1051
1052bool IbisParser::storeString( std::string& aDest, bool aMultiline )
1053{
1054 bool status = true;
1055
1057
1058 status &= readString( aDest );
1059
1061 m_continuingString = &aDest;
1062
1063 status &= checkEndofLine();
1064 return status;
1065}
1066
1067
1069{
1071
1072 std::string strChar = "";
1073
1074 // We cannot stop at m_lineLength here, because lineLength could stop before |_char
1075 // if the char remains the same
1076
1077 char c = m_buffer[m_lineOffset + m_lineIndex++];
1078 char d = c;
1079
1080 if( !( c == '!' || c == '"' || c == '#' || c == '$' || c == '%' || c == '&' || c == '\''
1081 || c == '(' || c == ')' || c == '*' || c == ',' || c == ':' || c == ';' || c == '<'
1082 || c == '>' || c == '?' || c == '@' || c == '\\' || c == '^' || c == '`' || c == '{'
1083 || c == '|' || c == '}' || c == '~' || c == ')' ) )
1084 {
1085 Report( _( "New comment character is invalid." ), RPT_SEVERITY_ERROR );
1086 }
1087
1089
1090 while( ( !isspace( c ) ) && c != 0 && c != '\n' )
1091 {
1092 strChar += c;
1094 }
1095
1096 if( strChar != "_char" )
1097 {
1098 Report( _( "Invalid syntax. Should be |_char or &_char, etc..." ), RPT_SEVERITY_ERROR );
1099 return false;
1100 }
1101
1102 while( isspace( c ) && c != 0 && c != '\n' && c != d )
1103 {
1105 }
1106
1107 if( ( !isspace( c ) ) && c != d )
1108 {
1109 Report( _( "No extra argument was expected" ), RPT_SEVERITY_ERROR );
1110 return false;
1111 }
1112
1113 m_commentChar = d;
1114
1115
1117
1118 return true;
1119}
1120
1122{
1123 std::string keyword = "";
1124 //"Keywords must be enclosed in square brackets, “[]”, and must start in column 1 of the line."
1125 //"No space or tab is allowed immediately after the opening bracket “[” or immediately"
1126 // "before the closing bracket “]"
1127
1128 if( m_buffer[m_lineOffset + m_lineIndex] != '[' )
1129 {
1130 // We return an empty keyword, this should stop the parser.
1131 return "";
1132 }
1133
1134 m_lineIndex++;
1135
1136 char c;
1138
1139 while( ( c != ']' )
1140 && ( m_lineIndex
1141 < m_lineLength ) ) // We know the maximum keyword length, we could add a condition.
1142 {
1143 // "Underscores and spaces are equivalent in keywords"
1144 if( c == ' ' )
1145 {
1146 c = '_';
1147 }
1148 keyword += c;
1150 }
1151
1152 return keyword;
1153}
1154
1155bool IbisParser::changeContext( std::string& aKeyword )
1156{
1157 bool status = true;
1158
1159 if( status )
1160 {
1161 switch( m_context )
1162 {
1163 case IBIS_PARSER_CONTEXT::HEADER: status &= m_ibisFile.m_header.Check(); break;
1165 case IBIS_PARSER_CONTEXT::MODEL: status &= m_currentModel->Check(); break;
1169 Report( "Cannot change context after [END]" );
1170 status = false;
1171 break;
1172
1173 default: Report( "Changing context from an undefined context" );
1174 }
1175 }
1176
1177 if( !compareIbisWord( aKeyword.c_str(), "End" ) && status )
1178 {
1179 //New context
1180 if( compareIbisWord( aKeyword.c_str(), "Component" ) )
1181 {
1184 status &= storeString( m_currentComponent->m_name, false );
1186 }
1187 else if( compareIbisWord( aKeyword.c_str(), "Model_Selector" ) )
1188 {
1190 status &= storeString( MS.m_name, false );
1191 m_ibisFile.m_modelSelectors.push_back( MS );
1195 }
1196 else if( compareIbisWord( aKeyword.c_str(), "Model" ) )
1197 {
1198 IbisModel model( m_reporter );
1202 status &= storeString( model.m_name, false );
1203 m_ibisFile.m_models.push_back( model );
1204 m_currentModel = &( m_ibisFile.m_models.back() );
1207 }
1208 else if( compareIbisWord( aKeyword.c_str(), "Define_Package_Model" ) )
1209 {
1211 PM.m_resistanceMatrix = std::unique_ptr<IBIS_MATRIX>( new IBIS_MATRIX( m_reporter ) );
1212 PM.m_capacitanceMatrix = std::unique_ptr<IBIS_MATRIX>( new IBIS_MATRIX( m_reporter ) );
1213 PM.m_inductanceMatrix = std::unique_ptr<IBIS_MATRIX>( new IBIS_MATRIX( m_reporter ) );
1214
1218
1219 PM.m_resistanceMatrix->m_dim = -1;
1220 PM.m_capacitanceMatrix->m_dim = -1;
1221 PM.m_inductanceMatrix->m_dim = -1;
1222
1223 status &= storeString( PM.m_name, false );
1224
1225 m_ibisFile.m_packageModels.push_back( PM );
1228 }
1229 else if( compareIbisWord( aKeyword.c_str(), "End_Package_Model" ) )
1230 {
1231 if( m_currentComponent != nullptr )
1232 {
1235 }
1236 else // .pkg file, we just go back to header, to get the [END] keyword
1237 { // This will cause the header to be checked twice.
1240 }
1241 }
1242 else
1243 {
1244 status = false;
1245 std::string context_string;
1246
1247 switch( m_context )
1248 {
1249 case IBIS_PARSER_CONTEXT::HEADER: context_string += "HEADER"; break;
1250 case IBIS_PARSER_CONTEXT::COMPONENT: context_string += "COMPONENT"; break;
1251 case IBIS_PARSER_CONTEXT::MODELSELECTOR: context_string += "MODEL_SELECTOR"; break;
1252 case IBIS_PARSER_CONTEXT::MODEL: context_string += "MODEL"; break;
1253 case IBIS_PARSER_CONTEXT::PACKAGEMODEL: context_string += "PACKAGE_MODEL"; break;
1255 context_string += "PACKAGE_MODEL_MODEL_DATA";
1256 break;
1257 default: context_string += "???"; break;
1258 }
1259
1260 std::stringstream message;
1261 message << _( "Unknown keyword in " ) << context_string << _( " context: " ) << aKeyword;
1262 Report( message.str(), RPT_SEVERITY_ERROR );
1263 }
1264 }
1265 else
1266 {
1268 }
1269
1270 return status;
1271}
1272
1273
1274bool IbisParser::parseModelSelector( std::string& aKeyword )
1275{
1276 bool status = true;
1277
1278 if( !changeContext( aKeyword ) )
1279 {
1280 status = false;
1281 }
1282 return status;
1283}
1284
1285
1287{
1288 bool status = true;
1289 std::string str;
1290
1291 if( readWord( str ) )
1292 {
1293 status &= readDvdt( str, aDest.value[IBIS_CORNER::TYP] )
1294 && readDvdt( str, aDest.value[IBIS_CORNER::MIN] )
1295 && readDvdt( str, aDest.value[IBIS_CORNER::MAX] );
1296 }
1297 else
1298 {
1299 status = false;
1300 }
1301
1302 return status;
1303}
1304
1306{
1307 bool status = true;
1308
1310
1311 if( !readNumericSubparam( std::string( "R_load" ), m_currentModel->m_ramp.m_Rload ) )
1312 {
1313 std::string str;
1314
1315 if( readWord( str ) )
1316 {
1317 if( !strcmp( str.c_str(), "dV/dt_r" ) )
1318 {
1320 }
1321 else if( !strcmp( str.c_str(), "dV/dt_f" ) )
1322 {
1324 }
1325 else
1326 {
1327 Report( _( "Invalid ramp data" ), RPT_SEVERITY_ERROR );
1328 status = false;
1329 }
1330 }
1331 }
1332 return status;
1333}
1334
1335
1336bool IbisParser::parseModel( std::string& aKeyword )
1337{
1338 bool status = false;
1339
1340 if( compareIbisWord( aKeyword.c_str(), "Voltage_Range" ) )
1342 else if( compareIbisWord( aKeyword.c_str(), "Temperature_Range" ) )
1344 else if( compareIbisWord( aKeyword.c_str(), "GND_Clamp" ) )
1346 else if( compareIbisWord( aKeyword.c_str(), "POWER_Clamp" ) )
1348 else if( compareIbisWord( aKeyword.c_str(), "Pulldown" ) )
1350 else if( compareIbisWord( aKeyword.c_str(), "Pullup" ) )
1352 else if( compareIbisWord( aKeyword.c_str(), "Rising_Waveform" ) )
1353 status = readWaveform( nullptr, IBIS_WAVEFORM_TYPE::RISING );
1354 else if( compareIbisWord( aKeyword.c_str(), "Falling_Waveform" ) )
1355 status = readWaveform( nullptr, IBIS_WAVEFORM_TYPE::FALLING );
1356 else if( compareIbisWord( aKeyword.c_str(), "Ramp" ) )
1357 status = readRamp();
1358 else if( compareIbisWord( aKeyword.c_str(), "Pullup_Reference" ) )
1360 else if( compareIbisWord( aKeyword.c_str(), "Pulldown_Reference" ) )
1362 else if( compareIbisWord( aKeyword.c_str(), "POWER_Clamp_Reference" ) )
1364 else if( compareIbisWord( aKeyword.c_str(), "GND_Clamp_Reference" ) )
1366 else if( compareIbisWord( aKeyword.c_str(), "Rac" ) )
1368 else if( compareIbisWord( aKeyword.c_str(), "Cac" ) )
1370 else if( compareIbisWord( aKeyword.c_str(), "Rpower" ) )
1372 else if( compareIbisWord( aKeyword.c_str(), "Rgnd" ) )
1374 else
1375 {
1376 status = changeContext( aKeyword );
1377 }
1378 return status;
1379}
1380
1382{
1384 std::string str;
1385
1386 if( readWord( str ) )
1387 m_currentPackageModel->m_pins.push_back( str );
1388
1389 return true;
1390}
1391
1392
1393bool IbisParser::readMatrixBanded( std::string aKeyword, IBIS_MATRIX_BANDED& aDest )
1394{
1395 bool status = true;
1397
1398 if( compareIbisWord( aKeyword.c_str(), "Bandwidth" ) )
1399 {
1401 {
1402 status &= readInt( aDest.m_bandwidth );
1403 if( status )
1404 {
1405 aDest.m_data.resize( aDest.m_bandwidth * aDest.m_dim );
1406 }
1407 }
1408 else
1409 {
1410 status = false;
1411 Report( _( "Cannot specify a bandwidth for that kind of matrix" ), RPT_SEVERITY_ERROR );
1412 }
1413 }
1414 if( !compareIbisWord( aKeyword.c_str(), "Dummy" ) )
1415 {
1416 int i;
1417 for( i = 0; i < aDest.m_bandwidth; i++ )
1418 {
1419 if( i + m_currentMatrixRowIndex >= aDest.m_bandwidth )
1420 {
1421 Report( "Too much data for this matrix row", RPT_SEVERITY_ERROR );
1422 status = false;
1423 break;
1424 }
1425
1426 int index = i + m_currentMatrixRow * aDest.m_bandwidth;
1427
1428 if( !readDouble( aDest.m_data[index] ) )
1429 {
1430 Report( _( "Invalid row in matrix" ), RPT_SEVERITY_ERROR );
1431 status = false;
1432 break;
1433 }
1434 }
1436 }
1437
1438 return status;
1439}
1440
1441
1442bool IbisParser::readMatrixFull( std::string aKeyword, IBIS_MATRIX_FULL& aDest )
1443{
1444 bool status = true;
1446
1447 if( !compareIbisWord( aKeyword.c_str(), "Dummy" ) )
1448 {
1449 std::vector<std::string> values;
1450
1451 status &= readTableLine( values );
1452 int i;
1453 for( i = 0; i < (int)values.size(); i++ )
1454 {
1455 int index = i + m_currentMatrixRow * aDest.m_dim + m_currentMatrixRow;
1456 // + final m_currentMatrixRow because we don't fill the lower triangle.
1457
1458 if( i >= ( aDest.m_dim - m_currentMatrixRow - m_currentMatrixRowIndex ) )
1459 {
1460 Report( _( "Too much data for this matrix row." ), RPT_SEVERITY_ERROR );
1461 status = false;
1462 break;
1463 }
1464
1465 if( index >= aDest.m_dim * aDest.m_dim )
1466 {
1467 status = false;
1468 Report( _( "Too much data for this matrix." ), RPT_SEVERITY_ERROR );
1469 break;
1470 }
1471 if( !parseDouble( aDest.m_data[index], values.at( i ), true ) )
1472 {
1473 Report( _( "Can't read a matrix element" ), RPT_SEVERITY_ERROR );
1474 status = false;
1475 }
1476 else
1477 {
1478 }
1479 }
1481 }
1482 return status;
1483}
1484
1485
1486bool IbisParser::readMatrixSparse( std::string aKeyword, IBIS_MATRIX_SPARSE& aDest )
1487{
1488 bool status = true;
1489
1490 if( !compareIbisWord( aKeyword.c_str(), "Dummy" ) )
1491 {
1492 int subindex;
1493 double value;
1494
1495 if( readInt( subindex ) )
1496 {
1497 if( readDouble( value ) )
1498 {
1499 #if 0
1500 // Currently not used
1501 int index = subindex + m_currentMatrixRow * aDest.m_dim + m_currentMatrixRow;
1502 #endif
1503 }
1504 else
1505 {
1506 Report( _( "Can't read a matrix element" ), RPT_SEVERITY_ERROR );
1507 }
1508 }
1509 else
1510 {
1511 Report( _( "Can't read a matrix index" ), RPT_SEVERITY_ERROR );
1512 }
1513 }
1514 return status;
1515}
1516
1517bool IbisParser::readMatrix( std::shared_ptr<IBIS_MATRIX> aDest )
1518{
1519 bool status = true;
1520 std::string str;
1521
1522 bool init = false;
1523
1524 if( aDest != nullptr )
1525 {
1526 if( aDest->m_type != IBIS_MATRIX_TYPE::BANDED && aDest->m_type != IBIS_MATRIX_TYPE::FULL
1527 && aDest->m_type != IBIS_MATRIX_TYPE::SPARSE )
1528 {
1529 init = false;
1530 }
1531 else
1532 {
1533 init = true;
1534 }
1535 }
1536 else
1537 {
1538 Report( "Matrix pointer is null." );
1539 status = false;
1540 }
1541
1542 if( m_continue != IBIS_PARSER_CONTINUE::MATRIX && status )
1543 {
1544 if( !init )
1545 {
1546 if( readWord( str ) )
1547 {
1548 IBIS_MATRIX* matrix;
1549
1550 if( compareIbisWord( str.c_str(), "Banded_matrix" ) )
1551 {
1552 matrix = static_cast<IBIS_MATRIX*>( new IBIS_MATRIX_BANDED( m_reporter ) );
1553 aDest = static_cast<std::shared_ptr<IBIS_MATRIX>>( matrix );
1554 m_currentMatrix = aDest;
1557 }
1558 else if( compareIbisWord( str.c_str(), "Full_matrix" ) )
1559 {
1560 matrix = static_cast<IBIS_MATRIX*>( new IBIS_MATRIX_FULL( m_reporter ) );
1561 aDest = static_cast<std::shared_ptr<IBIS_MATRIX>>( matrix );
1562 m_currentMatrix = aDest;
1566 }
1567 else if( compareIbisWord( str.c_str(), "Sparse_matrix" ) )
1568 {
1569 matrix = static_cast<IBIS_MATRIX*>( new IBIS_MATRIX_SPARSE( m_reporter ) );
1570 aDest = static_cast<std::shared_ptr<IBIS_MATRIX>>( matrix );
1571 m_currentMatrix = aDest;
1572 m_currentMatrix->m_data.resize( matrix->m_dim * matrix->m_dim );
1575 }
1576 else
1577 {
1578 status = false;
1579 Report( _( "Unknown matrix type" ), RPT_SEVERITY_ERROR );
1580 Report( str, RPT_SEVERITY_INFO );
1582 }
1583 }
1584 else
1585 {
1586 status = false;
1587 Report( _( "Missing matrix type" ), RPT_SEVERITY_ERROR );
1588 }
1589 }
1590 else
1591 {
1592 status = false;
1593 Report( _( " Matrix is already init. But m_continue was not set ( internal error )" ) );
1594 }
1595 }
1596 else
1597 {
1598 if( aDest != nullptr )
1599 {
1600 // If m_continue is set, ( and no keyword ) then it is a row
1601 switch( aDest->m_type )
1602 {
1604 readMatrixBanded( std::string( "Dummy" ),
1605 *static_cast<IBIS_MATRIX_BANDED*>( aDest.get() ) );
1606 break;
1608 readMatrixFull( std::string( "Dummy" ),
1609 *static_cast<IBIS_MATRIX_FULL*>( aDest.get() ) );
1610 break;
1612 readMatrixSparse( std::string( "Dummy" ),
1613 *static_cast<IBIS_MATRIX_SPARSE*>( aDest.get() ) );
1614 break;
1616 default:
1617 {
1618 status = false;
1619 Report( _( "Tried to read a row from an undefined matrix" ) );
1620 }
1621 }
1622 }
1623 else
1624 {
1625 Report( _( "matrix pointer is null" ) );
1626 }
1627 }
1628 return status;
1629}
1630
1631bool IbisParser::parsePackageModelModelData( std::string& aKeyword )
1632{
1633 bool status = true;
1634
1635 if( compareIbisWord( aKeyword.c_str(), "Resistance_Matrix" ) )
1636 {
1637 IBIS_MATRIX dest( m_reporter ), source( m_reporter );
1639 }
1640 else if( compareIbisWord( aKeyword.c_str(), "Capacitance_Matrix" ) )
1641 {
1643 }
1644 else if( compareIbisWord( aKeyword.c_str(), "Inductance_Matrix" ) )
1645 {
1647 }
1648 else if( compareIbisWord( aKeyword.c_str(), "Bandwidth" ) )
1649 {
1650 status &= readMatrixBanded( aKeyword,
1651 *static_cast<IBIS_MATRIX_BANDED*>( m_currentMatrix.get() ) );
1652 }
1653 else if( compareIbisWord( aKeyword.c_str(), "Row" ) )
1654 {
1655 status &= readInt( m_currentMatrixRow );
1656 m_currentMatrixRow--; // The matrix starts at 0
1657 m_currentMatrixRowIndex = 0; // The matrix starts at 0*/
1659 }
1660 else if( compareIbisWord( aKeyword.c_str(), "End_Model_Data" ) )
1661 {
1664 }
1665 else
1666 {
1667 if( !changeContext( aKeyword ) )
1668 {
1669 status = false;
1670 }
1671 }
1672 return status;
1673}
1674
1675bool IbisParser::parsePackageModel( std::string& aKeyword )
1676{
1677 bool status = true;
1678
1679 if( compareIbisWord( aKeyword.c_str(), "Manufacturer" ) )
1681 else if( compareIbisWord( aKeyword.c_str(), "OEM" ) )
1682 status &= storeString( m_currentPackageModel->m_OEM, false );
1683 else if( compareIbisWord( aKeyword.c_str(), "Description" ) )
1684 status &= storeString( m_currentPackageModel->m_description, false );
1685 else if( compareIbisWord( aKeyword.c_str(), "Number_of_Pins" ) )
1687 else if( compareIbisWord( aKeyword.c_str(), "Pin_Numbers" ) )
1688 status &= readPackageModelPins();
1689 else if( compareIbisWord( aKeyword.c_str(), "Model_Data" ) )
1690 {
1693 }
1694 else
1695 {
1696 if( !changeContext( aKeyword ) )
1697 {
1698 status = false;
1699 }
1700 }
1701 return status;
1702}
1703
1705{
1706 bool status = true;
1707
1709
1710 if( !readWord( model.m_modelName ) )
1711 return false;
1712
1713 status &= readString( model.m_modelDescription );
1714 m_currentModelSelector->m_models.push_back( model );
1715
1716 return status;
1717}
1718
1719bool IbisParser::readNumericSubparam( std::string aSubparam, double& aDest )
1720{
1721 std::string paramName;
1722 bool status = true;
1723
1724 if( aSubparam.size() >= (size_t)m_lineLength )
1725 {
1726 // Continuing would result in an overflow
1727 return false;
1728 }
1729
1730 int old_index = m_lineIndex;
1731 m_lineIndex = 0;
1732
1733
1734 for( size_t i = 0; i < aSubparam.size(); i++ )
1735 {
1736 paramName += m_buffer[m_lineOffset + m_lineIndex++];
1737 }
1738
1739 if( strcmp( paramName.c_str(), aSubparam.c_str() ) )
1740 {
1741 m_lineIndex = old_index;
1742 return false;
1743 }
1744
1746
1747 status &= m_buffer[m_lineOffset + m_lineIndex++] == '=';
1748
1749 if( status )
1750 {
1752 status &= readDouble( aDest );
1753 }
1754
1755 if( !status )
1756 {
1757 m_lineIndex = old_index;
1758 }
1759
1760 return status;
1761}
1762
1763
1765{
1766 bool status = true;
1767
1769
1770 std::string strValue;
1771
1772 if( !readDouble( aDest.value[IBIS_CORNER::TYP] ) )
1773 {
1774 Report( _( "Typ-Min-Max Values requires at least Typ." ), RPT_SEVERITY_ERROR );
1775 return false;
1776 }
1777
1780
1781 return status;
1782}
1783
1784bool IbisParser::readTypMinMaxValueSubparam( std::string aSubparam, TypMinMaxValue& aDest )
1785{
1786 std::string paramName;
1787 bool status = true;
1788
1789 m_lineIndex = 0; // rewind
1790
1791 if( aSubparam.size() < (size_t)m_lineLength )
1792 {
1793 for( size_t i = 0; i < aSubparam.size(); i++ )
1794 {
1795 paramName += m_buffer[m_lineOffset + m_lineIndex++];
1796 }
1797
1798 if( !strcmp( paramName.c_str(), aSubparam.c_str() ) )
1799 {
1800 readTypMinMaxValue( aDest );
1801 }
1802 else
1803 {
1804 status = false;
1805 }
1806 }
1807 else
1808 {
1809 status = false;
1810 }
1811
1812 return status;
1813}
1814
1816{
1817 bool status = true;
1818
1819 std::string subparam;
1820 if( readWord( subparam ) )
1821 {
1822 switch( m_continue )
1823 {
1825
1826 if( !strcmp( subparam.substr( 0, 10 ).c_str(), "Model_type" ) )
1827 {
1828 if( readWord( subparam ) )
1829 {
1830 if( !strcmp( subparam.c_str(), "Input" ) )
1832 else if( !strcmp( subparam.c_str(), "Output" ) )
1834 else if( !strcmp( subparam.c_str(), "I/O" ) )
1836 else if( !strcmp( subparam.c_str(), "3-state" ) )
1838 else if( !strcmp( subparam.c_str(), "Open_drain" ) )
1840 else if( !strcmp( subparam.c_str(), "I/O_Open_drain" ) )
1842 else if( !strcmp( subparam.c_str(), "Open_sink" ) )
1844 else if( !strcmp( subparam.c_str(), "I/O_open_sink" ) )
1846 else if( !strcmp( subparam.c_str(), "Open_source" ) )
1848 else if( !strcmp( subparam.c_str(), "I/O_open_source" ) )
1850 else if( !strcmp( subparam.c_str(), "Input_ECL" ) )
1852 else if( !strcmp( subparam.c_str(), "Output_ECL" ) )
1854 else if( !strcmp( subparam.c_str(), "I/O_ECL" ) )
1856 else if( !strcmp( subparam.c_str(), "3-state_ECL" ) )
1858 else if( !strcmp( subparam.c_str(), "Terminator" ) )
1860 else if( !strcmp( subparam.c_str(), "Series" ) )
1862 else if( !strcmp( subparam.c_str(), "Series_switch" ) )
1864 else
1865 {
1866 std::stringstream message;
1867 message << _( "Unknown Model_type " ) << subparam;
1868 Report( message.str(), RPT_SEVERITY_ERROR );
1869 status = false;
1870 }
1871 }
1872 else
1873 {
1874 Report( _( "Internal Error while reading model_type" ), RPT_SEVERITY_ERROR );
1875 status = false;
1876 }
1877 }
1878 else if( !strcmp( subparam.substr( 0, 7 ).c_str(), "Enable" ) )
1879 {
1880 if( readWord( subparam ) )
1881 {
1882 if( !strcmp( subparam.c_str(), "Active-High" ) )
1884 else if( !strcmp( subparam.c_str(), "Active-Low" ) )
1886 else
1887 {
1888 std::stringstream message;
1889 message << _( "Unknown Enable: " ) << subparam;
1890 Report( message.str(), RPT_SEVERITY_ERROR );
1891 status = false;
1892 }
1893 }
1894 else
1895 {
1896 Report( _( "Internal Error while reading Enable" ), RPT_SEVERITY_ERROR );
1897 status = false;
1898 }
1899 }
1900 else if( subparam.substr( 0, 9 ) == "Polarity" )
1901 {
1902 if( readWord( subparam ) )
1903 {
1904 if( subparam == "Inverting" )
1906 else if( subparam == "Non-Inverting" )
1908 else
1909 {
1910 std::stringstream message;
1911 message << _( "Unknown polarity " ) << subparam;
1912 Report( message.str(), RPT_SEVERITY_ERROR );
1913 status = false;
1914 }
1915 }
1916 else
1917 {
1918 Report( _( "Internal Error while reading Enable" ), RPT_SEVERITY_ERROR );
1919 status = false;
1920 }
1921 }
1922 else if( readNumericSubparam( std::string( "Vinl" ), m_currentModel->m_vinl ) )
1923 ;
1924 else if( readNumericSubparam( std::string( "Vinh" ), m_currentModel->m_vinh ) )
1925 ;
1926 else if( readNumericSubparam( std::string( "Vref" ), m_currentModel->m_vref ) )
1927 ;
1928 else if( readNumericSubparam( std::string( "Rref" ), m_currentModel->m_rref ) )
1929 ;
1930 else if( readNumericSubparam( std::string( "Cref" ), m_currentModel->m_cref ) )
1931 ;
1932 else if( readNumericSubparam( std::string( "Vmeas" ), m_currentModel->m_vmeas ) )
1933 ;
1934 else if( readTypMinMaxValueSubparam( std::string( "C_comp" ),
1936 ;
1937 else
1938 {
1939 status = false;
1940 }
1941
1943
1944 break;
1945
1946 default:
1947 status = false;
1948 Report( _( "Continued reading a model that did not begin. ( internal error )" ),
1950 }
1951 }
1952
1953 return status;
1954}
1955
1956
1957bool IbisParser::parseHeader( std::string& aKeyword )
1958{
1959 bool status = true;
1960
1961 if( compareIbisWord( aKeyword.c_str(), "IBIS_Ver" ) )
1962 {
1964 }
1965 else if( compareIbisWord( aKeyword.c_str(), "Comment_char" ) )
1966 {
1967 status &= changeCommentChar();
1968 }
1969 else if( compareIbisWord( aKeyword.c_str(), "File_Name" ) )
1970 {
1971 status &= storeString( m_ibisFile.m_header.m_fileName, false );
1972 }
1973 else if( compareIbisWord( aKeyword.c_str(), "File_Rev" ) )
1974 {
1976 }
1977 else if( compareIbisWord( aKeyword.c_str(), "Source" ) )
1978 {
1979 status &= storeString( m_ibisFile.m_header.m_source, true );
1980 }
1981 else if( compareIbisWord( aKeyword.c_str(), "Notes" ) )
1982 {
1983 status &= storeString( m_ibisFile.m_header.m_notes, true );
1984 }
1985 else if( compareIbisWord( aKeyword.c_str(), "Disclaimer" ) )
1986 {
1987 status &= storeString( m_ibisFile.m_header.m_disclaimer, true );
1988 }
1989 else if( compareIbisWord( aKeyword.c_str(), "Copyright" ) )
1990 {
1991 status &= storeString( m_ibisFile.m_header.m_copyright, true );
1992 }
1993 else if( compareIbisWord( aKeyword.c_str(), "Date" ) )
1994 {
1995 status &= storeString( m_ibisFile.m_header.m_date, false );
1996 }
1997 else
1998 {
1999 if( !changeContext( aKeyword ) )
2000 {
2001 status = false;
2002 }
2003 }
2004 return status;
2005}
2006
2007
2008bool IbisParser::parseComponent( std::string& aKeyword )
2009{
2010 bool status = true;
2011 if( compareIbisWord( aKeyword.c_str(), "Manufacturer" ) )
2012 {
2013 status &= storeString( m_currentComponent->m_manufacturer, true );
2014 }
2015 else if( compareIbisWord( aKeyword.c_str(), "Package" ) )
2016 {
2017 status &= readPackage();
2018 }
2019 else if( compareIbisWord( aKeyword.c_str(), "Pin" ) )
2020 {
2021 status &= readPin();
2022 }
2023 else if( compareIbisWord( aKeyword.c_str(), "Pin_Mapping" ) )
2024 {
2025 status &= readPinMapping();
2026 }
2027 else if( compareIbisWord( aKeyword.c_str(), "Diff_Pin" ) )
2028 {
2029 status &= readDiffPin();
2030 }
2031 /*
2032 // Not supported yet
2033 else if( aKeyword == "Die_Supply_Pads" )
2034 {
2035 status &= ReadDieSupplyPads();
2036 }*/
2037 else if( compareIbisWord( aKeyword.c_str(), "Package_Model" ) )
2038 {
2039 status &= storeString( m_currentComponent->m_packageModel, true );
2040 }
2041 else
2042 {
2043 if( !changeContext( aKeyword ) )
2044 {
2045 status = false;
2046 }
2047 }
2048 return status;
2049}
2050
2051bool IbisParser::readTableLine( std::vector<std::string>& aDest )
2052{
2053 aDest.clear();
2054
2055 while( m_lineIndex < m_lineLength )
2056 {
2057 std::string str;
2058
2059 while( ( !isspace( m_buffer[m_lineOffset + m_lineIndex] ) )
2060 && ( m_lineIndex < m_lineLength ) )
2061 {
2062 str += m_buffer[m_lineOffset + m_lineIndex++];
2063 }
2064
2065 if( str.size() > 0 )
2066 {
2067 aDest.push_back( str );
2068 }
2069 while( isspace( m_buffer[m_lineOffset + m_lineIndex] ) && ( m_lineIndex < m_lineLength ) )
2070 {
2071 m_lineIndex++;
2072 }
2073 }
2074 return true;
2075}
2076
2078{
2079 bool status = true;
2080
2081 std::vector<std::string> fields;
2082
2086
2087 readTableLine( fields );
2088
2089 int extraArg = ( m_continue == IBIS_PARSER_CONTINUE::NONE ) ? 1 : 0;
2090
2091 if( (int)fields.size() == ( 4 + extraArg ) )
2092 {
2093 TypMinMaxValue* cValue;
2094
2095 if( fields.at( 0 ) == "R_pkg" )
2096 cValue = R;
2097 else if( fields.at( 0 ) == "L_pkg" )
2098 cValue = L;
2099 else if( fields.at( 0 ) == "C_pkg" )
2100 cValue = C;
2101 else
2102 {
2103 Report( "Invalid field in [Package]" );
2104 return false;
2105 }
2106 status &= parseDouble( cValue->value[IBIS_CORNER::TYP], fields.at( 1 ), true );
2107 // Min / max values are optional, so don't update the status
2108 parseDouble( cValue->value[IBIS_CORNER::MIN], fields.at( 2 ), true );
2109 parseDouble( cValue->value[IBIS_CORNER::MAX], fields.at( 3 ), true );
2110 }
2111 else
2112 {
2113 if( fields.size() != 0 )
2114 {
2115 Report( _( "A [Package] line requires exactly 4 elements." ), RPT_SEVERITY_ERROR );
2116 status = false;
2117 }
2118 }
2120
2121 return status;
2122}
2123
2124
2126{
2127 bool status = true;
2128
2129 std::vector<std::string> fields;
2130
2131 m_lineIndex = 0;
2132 status &= readTableLine( fields );
2133
2135
2136 if( ( fields.size() == 3 ) )
2137 {
2138 if( m_continue == IBIS_PARSER_CONTINUE::COMPONENT_PIN ) // No info on first line
2139 {
2140 pin.m_pinName = fields.at( 0 );
2141 pin.m_signalName = fields.at( 1 );
2142 pin.m_modelName = fields.at( 2 );
2143 pin.m_Rcol = m_currentComponent->m_pins.back().m_Rcol;
2144 pin.m_Lcol = m_currentComponent->m_pins.back().m_Lcol;
2145 pin.m_Ccol = m_currentComponent->m_pins.back().m_Ccol;
2146
2147 m_currentComponent->m_pins.push_back( pin );
2148 }
2149 else
2150 {
2151 pin.m_dummy = true;
2152 }
2153 }
2154 else
2155 {
2156 if( m_continue == IBIS_PARSER_CONTINUE::COMPONENT_PIN ) // Not on the first line
2157 {
2158 pin.m_pinName = fields.at( 0 );
2159 pin.m_signalName = fields.at( 1 );
2160 pin.m_modelName = fields.at( 2 );
2161
2162 pin.m_Rcol = m_currentComponent->m_pins.back().m_Rcol;
2163 pin.m_Lcol = m_currentComponent->m_pins.back().m_Lcol;
2164 pin.m_Ccol = m_currentComponent->m_pins.back().m_Ccol;
2165
2166 if( pin.m_Rcol == 0 || pin.m_Lcol == 0 || pin.m_Ccol == 0 )
2167 {
2168 Report( _( "Invalid pin entry: 6 values from a table with only 3." ),
2170 status = false; // Did we just try to go from a 3 column table to a 6 ?
2171 }
2172 else
2173 {
2174 if( !parseDouble( pin.m_Rpin, fields.at( pin.m_Rcol ), true )
2175 || !parseDouble( pin.m_Lpin, fields.at( pin.m_Lcol ), true )
2176 || !parseDouble( pin.m_Cpin, fields.at( pin.m_Ccol ), true ) )
2177 {
2178 Report( _( "Can't read a R, L or C value for a pin." ), RPT_SEVERITY_ERROR );
2179 status = false;
2180 }
2181 }
2182 }
2183 else
2184 {
2185 for( int i = 3; i < 6; i++ )
2186 {
2187 if( fields.at( i ) == "R_pin" )
2188 {
2189 pin.m_Rcol = i;
2190 }
2191 else if( fields.at( i ) == "L_pin" )
2192 {
2193 pin.m_Lcol = i;
2194 }
2195 else if( fields.at( i ) == "C_pin" )
2196 {
2197 pin.m_Ccol = i;
2198 }
2199 else
2200 {
2201 Report( _( "Invalid field name in [Pin]" ), RPT_SEVERITY_ERROR );
2202 status = false;
2203 }
2204 }
2205
2206 if( pin.m_Rcol == 0 || pin.m_Lcol == 0 || pin.m_Ccol == 0 )
2207 {
2208 Report( _( "Missing argument in [Pin]" ), RPT_SEVERITY_ERROR );
2209 status = false;
2210 }
2211 pin.m_dummy = true;
2212 }
2213 }
2214
2215 m_currentComponent->m_pins.push_back( pin );
2217
2218
2219 return status;
2220}
2221
2222
2224{
2225 bool status = true;
2226
2227 std::vector<std::string> fields;
2228
2229 status &= readTableLine( fields );
2230
2231 IbisComponentPinMapping pinMapping( m_reporter );
2232
2233 if( m_continue == IBIS_PARSER_CONTINUE::NONE ) // No info on first line
2234 {
2236 }
2237 else
2238 {
2239 if( fields.size() != 0 )
2240 {
2241 if( fields.size() > 6 || fields.size() < 3 )
2242 {
2243 Report( _( "Wrong number of columns for pin mapping." ), RPT_SEVERITY_ERROR );
2244 status = false;
2245 }
2246 else
2247 {
2248 pinMapping.m_pinName = fields.at( 0 );
2249 pinMapping.m_PDref = fields.at( 1 );
2250 pinMapping.m_PUref = fields.at( 2 );
2251
2252 if( fields.size() > 3 )
2253 pinMapping.m_GNDClampRef = fields.at( 3 );
2254
2255 if( fields.size() > 4 )
2256 pinMapping.m_POWERClampRef = fields.at( 4 );
2257
2258 if( fields.size() > 5 )
2259 pinMapping.m_extRef = fields.at( 5 );
2260 }
2261 m_currentComponent->m_pinMappings.push_back( pinMapping );
2262 }
2263 }
2264 return status;
2265}
2266
2267
2269{
2270 bool status = true;
2271
2272 m_lineIndex = 0; // rewind
2274
2275 if( m_continue == IBIS_PARSER_CONTINUE::NONE ) // No info on first line
2276 {
2278 }
2279 else
2280 {
2281 if( !readWord( entry.pinA ) )
2282 {
2283 Report( _( "Incorrect diff pin name" ), RPT_SEVERITY_ERROR );
2284 status = false;
2285 }
2286 if( !readWord( entry.pinB ) )
2287 {
2288 Report( _( "Incorrect inv_pin name" ), RPT_SEVERITY_ERROR );
2289 status = false;
2290 }
2291 if( status )
2292 {
2293 m_currentComponent->m_diffPin.m_entries.push_back( entry );
2294 }
2295 }
2296 return status;
2297}
2298
2299
2301{
2302 bool status = true;
2303
2305
2306 IVtableEntry entry( m_reporter );
2307
2309 {
2310 std::string str;
2311
2312 status &= readDouble( entry.V );
2313
2314 if( status && readTypMinMaxValue( entry.I ) )
2315 {
2316 aDest.m_entries.push_back( entry );
2317 }
2318 }
2319
2321 m_currentIVtable = &aDest;
2322
2323
2324 return status;
2325}
2326
2328{
2329 bool status = true;
2331
2332 VTtableEntry entry( m_reporter );
2333
2335 {
2336 std::string str;
2337 status &= readDouble( entry.t );
2338 status &= readTypMinMaxValue( entry.V );
2339 }
2340
2342 m_currentVTtable = &aDest;
2343
2344 if( status )
2345 {
2346 aDest.m_entries.push_back( entry );
2347 }
2348
2349 return status;
2350}
2351
2353{
2354 bool status = true;
2355
2356
2357 IbisWaveform* wf;
2358
2360 {
2361 wf = new IbisWaveform( m_reporter );
2362 wf->m_type = aType;
2363
2364 switch( aType )
2365 {
2367 case IBIS_WAVEFORM_TYPE::RISING: m_currentModel->m_risingWaveforms.push_back( wf ); break;
2368 default: Report( _( "Unknown waveform type" ), RPT_SEVERITY_ERROR ); status = false;
2369 }
2370 }
2371 else
2372 {
2373 if( aDest != nullptr )
2374 {
2375 wf = aDest;
2376 }
2377 else
2378 {
2379 Report( _( "Internal error detected, a waveform should exist" ), RPT_SEVERITY_ERROR );
2380 return false;
2381 }
2382 }
2383
2384
2385 if( status & !isLineEmptyFromCursor() )
2386 {
2387 // readNumericSubparam() returns true if it could read the subparameter and store it
2388 // Testing all subparameters
2389 if( readNumericSubparam( std::string( "R_fixture" ), wf->m_R_fixture ) )
2390 ;
2391 else if( readNumericSubparam( std::string( "L_fixture" ), wf->m_L_fixture ) )
2392 ;
2393 else if( readNumericSubparam( std::string( "C_fixture" ), wf->m_C_fixture ) )
2394 ;
2395 else if( readNumericSubparam( std::string( "V_fixture" ), wf->m_V_fixture ) )
2396 ;
2397 else if( readNumericSubparam( std::string( "V_fixture_min" ), wf->m_V_fixture_min ) )
2398 ;
2399 else if( readNumericSubparam( std::string( "V_fixture_max" ), wf->m_V_fixture_max ) )
2400 ;
2401 else if( readNumericSubparam( std::string( "R_dut" ), wf->m_R_fixture ) )
2402 ;
2403 else if( readNumericSubparam( std::string( "L_dut" ), wf->m_L_fixture ) )
2404 ;
2405 else if( readNumericSubparam( std::string( "C_dut" ), wf->m_C_fixture ) )
2406 ;
2407 // The line is not a subparameter, then let's try to read a VT table entry
2409 {
2410 status = false;
2411 }
2412 }
2413 m_currentWaveform = wf;
2415 return status;
2416}
2417
2419{
2420 bool status = true;
2421 char c;
2422 std::string keyword = getKeyword();
2423
2424 if( keyword.size() > 0 ) // New keyword
2425 {
2426
2428 {
2430 }
2431 switch( m_context )
2432 {
2433 case IBIS_PARSER_CONTEXT::HEADER: status &= parseHeader( keyword ); break;
2434 case IBIS_PARSER_CONTEXT::COMPONENT: status &= parseComponent( keyword ); break;
2435 case IBIS_PARSER_CONTEXT::MODELSELECTOR: status &= parseModelSelector( keyword ); break;
2436 case IBIS_PARSER_CONTEXT::MODEL: status &= parseModel( keyword ); break;
2437 case IBIS_PARSER_CONTEXT::PACKAGEMODEL: status &= parsePackageModel( keyword ); break;
2439 status &= parsePackageModelModelData( keyword );
2440 break;
2441 default:
2442 {
2443 status = false;
2444 Report( _( "Internal error: Bad parser context." ), RPT_SEVERITY_ERROR );
2445 }
2446 }
2447 }
2448 else
2449 {
2451 if( m_lineIndex == m_lineLength )
2452 {
2453 // That was an empty line
2454 return true;
2455 }
2456
2457 // No new keyword ? Then it is the continuation of the previous one !
2458 switch( m_continue )
2459 {
2462 *m_continuingString += '\n';
2463 status &= readString( *m_continuingString );
2464 break;
2466 case IBIS_PARSER_CONTINUE::COMPONENT_PIN: status &= readPin(); break;
2470 case IBIS_PARSER_CONTINUE::MODEL: status &= readModel(); break;
2475 break;
2476 case IBIS_PARSER_CONTINUE::RAMP: status &= readRamp(); break;
2480 default:
2481 Report( _( "Missing keyword." ), RPT_SEVERITY_ERROR );
2482 return false;
2483 break;
2484 }
2485 }
2487
2488 while( ( c != '\n' ) && ( c != 0 ) ) // Go to the end of line
2489 {
2491 }
2492 return status;
2493}
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:67
IBIS_REPORTER * m_reporter
Definition: ibis_parser.h:58
std::vector< double > m_data
Definition: ibis_parser.h:129
bool Check() override
Check if the data held by the object is valid.
Definition: ibis_parser.cpp:60
bool Check() override
Check if the data held by the object is valid.
Definition: ibis_parser.cpp:89
std::vector< double > m_data
Definition: ibis_parser.h:152
bool Check() override
Check if the data held by the object is valid.
std::vector< double > m_data
Definition: ibis_parser.h:140
TypMinMaxValue I
Definition: ibis_parser.h:349
bool Check() override
Check if the data held by the object is valid.
double InterpolatedI(double aV, IBIS_CORNER aCorner)
Interpolate the IV table.
std::vector< IVtableEntry > m_entries
Definition: ibis_parser.h:360
std::string Spice(int aN, std::string aPort1, std::string aPort2, std::string aModelName, IBIS_CORNER aCorner)
Interpolate the IV table.
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_Cpkg
Definition: ibis_parser.h:204
TypMinMaxValue m_Lpkg
Definition: ibis_parser.h:203
TypMinMaxValue m_Rpkg
Definition: ibis_parser.h:202
std::string m_GNDClampRef
Definition: ibis_parser.h:250
std::string m_POWERClampRef
Definition: ibis_parser.h:251
bool Check() override
Check if the data held by the object is valid.
std::string m_signalName
Definition: ibis_parser.h:221
std::string m_pinName
Definition: ibis_parser.h:220
std::string m_modelName
Definition: ibis_parser.h:222
std::string m_manufacturer
Definition: ibis_parser.h:299
std::string m_packageModel
Definition: ibis_parser.h:303
std::vector< IbisComponentPinMapping > m_pinMappings
Definition: ibis_parser.h:302
IbisComponentPackage m_package
Definition: ibis_parser.h:300
bool Check() override
Check if the data held by the object is valid.
IbisDiffPin m_diffPin
Definition: ibis_parser.h:306
std::string m_name
Definition: ibis_parser.h:298
std::vector< IbisComponentPin > m_pins
Definition: ibis_parser.h:301
std::string pinB
Definition: ibis_parser.h:270
std::string pinA
Definition: ibis_parser.h:269
std::vector< IbisDiffPinEntry > m_entries
Definition: ibis_parser.h:283
std::vector< IbisComponent > m_components
Definition: ibis_parser.h:616
IbisHeader m_header
Definition: ibis_parser.h:615
std::vector< IbisPackageModel > m_packageModels
Definition: ibis_parser.h:619
std::vector< IbisModel > m_models
Definition: ibis_parser.h:618
std::vector< IbisModelSelector > m_modelSelectors
Definition: ibis_parser.h:617
bool Check() override
Check if the data held by the object is valid.
std::string m_fileName
Definition: ibis_parser.h:171
std::string m_copyright
Definition: ibis_parser.h:176
std::string m_notes
Definition: ibis_parser.h:174
double m_ibisVersion
Definition: ibis_parser.h:169
std::string m_date
Definition: ibis_parser.h:173
std::string m_source
Definition: ibis_parser.h:172
double m_fileRevision
Definition: ibis_parser.h:170
std::string m_disclaimer
Definition: ibis_parser.h:175
std::string m_modelName
Definition: ibis_parser.h:315
std::string m_modelDescription
Definition: ibis_parser.h:316
bool Check() override
Check if the data held by the object is valid.
std::string m_name
Definition: ibis_parser.h:330
std::vector< IbisModelSelectorEntry > m_models
Definition: ibis_parser.h:331
IBIS_MODEL_TYPE m_type
Definition: ibis_parser.h:544
double m_cref
Definition: ibis_parser.h:551
IVtable m_pullup
Definition: ibis_parser.h:570
TypMinMaxValue m_Cac
Definition: ibis_parser.h:567
TypMinMaxValue m_pullupReference
Definition: ibis_parser.h:560
double m_vmeas
Definition: ibis_parser.h:552
IVtable m_pulldown
Definition: ibis_parser.h:571
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_Rac
Definition: ibis_parser.h:566
std::vector< IbisWaveform * > m_risingWaveforms
Definition: ibis_parser.h:572
IVtable m_POWERClamp
Definition: ibis_parser.h:569
TypMinMaxValue m_Rgnd
Definition: ibis_parser.h:564
TypMinMaxValue m_POWERClampReference
Definition: ibis_parser.h:563
IVtable m_GNDClamp
Definition: ibis_parser.h:568
IbisRamp m_ramp
Definition: ibis_parser.h:574
TypMinMaxValue m_C_comp
Definition: ibis_parser.h:557
double m_rref
Definition: ibis_parser.h:550
IBIS_MODEL_ENABLE m_enable
Definition: ibis_parser.h:553
TypMinMaxValue m_temperatureRange
Definition: ibis_parser.h:559
std::vector< IbisWaveform * > m_fallingWaveforms
Definition: ibis_parser.h:573
TypMinMaxValue m_pulldownReference
Definition: ibis_parser.h:561
double m_vref
Definition: ibis_parser.h:549
TypMinMaxValue m_GNDClampReference
Definition: ibis_parser.h:562
double m_vinh
Definition: ibis_parser.h:548
double m_vinl
Definition: ibis_parser.h:547
TypMinMaxValue m_voltageRange
Definition: ibis_parser.h:558
TypMinMaxValue m_Rpower
Definition: ibis_parser.h:565
std::string m_name
Definition: ibis_parser.h:543
std::vector< std::string > m_pins
Definition: ibis_parser.h:595
std::shared_ptr< IBIS_MATRIX > m_resistanceMatrix
Definition: ibis_parser.h:597
std::string m_OEM
Definition: ibis_parser.h:592
std::shared_ptr< IBIS_MATRIX > m_inductanceMatrix
Definition: ibis_parser.h:599
bool Check() override
Check if the data held by the object is valid.
std::string m_description
Definition: ibis_parser.h:593
std::string m_name
Definition: ibis_parser.h:590
std::shared_ptr< IBIS_MATRIX > m_capacitanceMatrix
Definition: ibis_parser.h:598
std::string m_manufacturer
Definition: ibis_parser.h:591
std::vector< char > m_buffer
Definition: ibis_parser.h:662
char m_commentChar
Definition: ibis_parser.h:661
long m_lineCounter
Definition: ibis_parser.h:660
IBIS_PARSER_CONTINUE m_continue
Definition: ibis_parser.h:799
bool readPin()
bool changeCommentChar()
Ibis can change the character used for comments.
bool getNextLine()
Load the next line.
bool parseComponent(std::string &aKeyword)
Parse a single keyword in the component context.
bool parseModel(std::string &aKeyword)
Parse a single keyword in the model selector context.
bool readMatrixFull(std::string, IBIS_MATRIX_FULL &aDest)
VTtable * m_currentVTtable
Definition: ibis_parser.h:677
bool isLineEmptyFromCursor()
void printLine()
Print the current line.
bool readModelSelector()
bool changeContext(std::string &aKeyword)
int m_currentMatrixRowIndex
Definition: ibis_parser.h:675
std::string getKeyword()
bool parseDouble(double &aDest, std::string &aStr, bool aAllowModifiers=false)
Parse a double according to the ibis standard.
bool onNewLine()
Parse the current line.
bool readWord(std::string &aDest)
bool readTypMinMaxValue(TypMinMaxValue &aDest)
bool compareIbisWord(const std::string &a, const std::string &b)
compare two strings without being case sensitive
Definition: ibis_parser.cpp:50
int m_currentMatrixRow
Definition: ibis_parser.h:674
IbisComponent * m_currentComponent
Definition: ibis_parser.h:669
std::shared_ptr< IBIS_MATRIX > m_currentMatrix
Definition: ibis_parser.h:673
int m_lineLength
Definition: ibis_parser.h:666
int m_lineIndex
Definition: ibis_parser.h:665
bool readDvdt(std::string &aString, dvdt &aDest)
std::string * m_continuingString
Definition: ibis_parser.h:690
IbisModel * m_currentModel
Definition: ibis_parser.h:671
bool m_parrot
Definition: ibis_parser.h:658
bool readModel()
int m_lineOffset
Definition: ibis_parser.h:664
bool readNumericSubparam(std::string aSubparam, double &aDest)
bool parsePackageModelModelData(std::string &)
Parse a single keyword in the package model context.
IbisPackageModel * m_currentPackageModel
Definition: ibis_parser.h:672
bool readDouble(double &aDest)
IbisModelSelector * m_currentModelSelector
Definition: ibis_parser.h:670
bool readRamp()
bool checkEndofLine()
bool parsePackageModel(std::string &aKeyword)
Parse a single keyword in the model context.
bool readString(std::string &aDest)
bool readPinMapping()
bool readMatrixBanded(std::string, IBIS_MATRIX_BANDED &aDest)
bool readMatrix(std::shared_ptr< IBIS_MATRIX > aDest)
bool readTypMinMaxValueSubparam(std::string aSubparam, TypMinMaxValue &aDest)
bool readInt(int &aDest)
bool readPackage()
int m_bufferIndex
Definition: ibis_parser.h:663
IBIS_PARSER_CONTEXT m_context
Definition: ibis_parser.h:800
IbisFile m_ibisFile
Definition: ibis_parser.h:668
IVtable * m_currentIVtable
Definition: ibis_parser.h:676
bool readIVtableEntry(IVtable &aTable)
bool readVTtableEntry(VTtable &aTable)
bool ParseFile(std::string &aFileName)
Parse a file.
bool parseModelSelector(std::string &aKeyword)
Parse a single keyword in the component context.
bool readDiffPin()
void skipWhitespaces()
bool storeString(std::string &aDest, bool aMultiline)
bool readPackageModelPins()
bool readRampdvdt(dvdtTypMinMax &aDest)
bool readTableLine(std::vector< std::string > &aDest)
bool readMatrixSparse(std::string, IBIS_MATRIX_SPARSE &aDest)
bool parseHeader(std::string &aKeyword)
Parse a single keyword in the header context.
bool readWaveform(IbisWaveform *aDest, IBIS_WAVEFORM_TYPE aType)
IbisWaveform * m_currentWaveform
Definition: ibis_parser.h:678
dvdtTypMinMax m_rising
Definition: ibis_parser.h:480
bool Check() override
Check if the data held by the object is valid.
double m_Rload
Definition: ibis_parser.h:481
dvdtTypMinMax m_falling
Definition: ibis_parser.h:479
double m_L_fixture
Definition: ibis_parser.h:504
double m_V_fixture
Definition: ibis_parser.h:505
VTtable m_table
Definition: ibis_parser.h:497
double m_V_fixture_min
Definition: ibis_parser.h:506
IBIS_WAVEFORM_TYPE m_type
Definition: ibis_parser.h:498
double m_V_fixture_max
Definition: ibis_parser.h:507
double m_R_fixture
Definition: ibis_parser.h:502
double m_C_fixture
Definition: ibis_parser.h:503
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
bool Check() override
Check if the data held by the object is valid.
double value[3]
Definition: ibis_parser.h:186
TypMinMaxValue V
Definition: ibis_parser.h:404
std::vector< VTtableEntry > m_entries
Definition: ibis_parser.h:414
dvdt value[3]
Definition: ibis_parser.h:464
bool Check() override
Check if the data held by the object is valid.
double m_dv
Definition: ibis_parser.h:456
double m_dt
Definition: ibis_parser.h:457
static std::string strValue(double aValue)
Definition: eseries.cpp:44
bool isNumberNA(double aNumber)
#define _(x)
Definition: ibis_parser.cpp:46
#define NAN_NA
Definition: ibis_parser.h:35
IBIS_CORNER
Definition: ibis_parser.h:95
@ TYP
Definition: ibis_parser.h:96
@ MIN
Definition: ibis_parser.h:97
@ MAX
Definition: ibis_parser.h:98
#define IBIS_MAX_VERSION
Definition: ibis_parser.h:38
#define NAN_INVALID
Definition: ibis_parser.h:36
#define IBIS_MAX_LINE_LENGTH
Definition: ibis_parser.h:39
IBIS_WAVEFORM_TYPE
Definition: ibis_parser.h:487
CITER next(CITER it)
Definition: ptree.cpp:126
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
#define R()