Skip to content

russdill/pybis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

=================================
PyBIS -- Python based IBIS parser
=================================

Introduction
============

This module contains a python based IBIS parser. The latest IBIS specification
can be found here:

    http://eda.org/pub/ibis/ver5.0/ver5_0.txt

Parsing an IBIS file can be accomplished as follows:

    import pybis
    results = pybis.IBSParser().parse('test.ibs')
    print results.header.file_rev

The additional parsers 'PKGParser' and 'EBDParser' are available for parsing
'.pkg' and '.ebd' files respectively.

Handling Parse Results
======================

Parse results are return as a tree of 'IBISNode' objects. An 'IBISNode' object
is a python dict. Each key/value pair represents a section, keyword, or param.
Each value can be a:

    - IBISNode
    - Range
    - list
    - dict
    - numpy matrix
    - string
    - float
    - int
    - None

In the case of a dict or list, the children can be any of the above except dict
and list.

Children of an IBISNode can be accessed through the standard dict accessors as
well as with the python attribute accessors. Additionally, any accesses are
case insensitive and allow the use of a '_' in place of ' ' or '/', 'p' in
place of '+', and 'n' in place of '-':

    results.model["SSTL18"].model_spec.vinlp
    results.MODEL["SSTL18"].Model_Spec["Vinl+"]
    results["Model"]["SSTL18"]["Model Spec"].Vinlp

Objects represented by dict values, such as the set of components, do not have
this property.

If the specification indicates that a certain keyword is required in certain
circumstances or defaults to a certain value, the parser will ensure that
condition is met. For optional keywords, and if block or try/except block can
be used:

    if 'Copyright' in results.header:
        print results.header.copyright
    else:
        print 'Not specified'

    try:
        print results.header["Copyright"]
    except:
        print 'Not specified'

    print result.header.get('Copyright', 'Not specified')

A 'Range' type represents a typ/min/max set. It can be accessed through the
following methods:

    [0-2] -                  Return raw values (0 = typ, 1 = min, 2 = max).
    (0-2) -                  Return typ for min or max if they are 'None'.
    (0-2, invert=False) -    Ensure max > min.
    (0-2, invert=True) -     Ensure mix > max.
    .typ, .min, .max -       Easy accessors for (0-2).
    .norm -                  Return version of object where max > min.
    .inv -                   return version of object where min > max.

A keyword such as 'Pin', 'Pin Mapping', or 'Pin EMI' that names columns, is
stored as a dict of IBISNode's indexed by the key in the first column. The
column names are the keys of the IBISNode's. This is also true of sections
that implicitly name columns such as 'Driver Schedule'.

Keywords that represent waveforms or I-V curves such as 'Pulldown', 'GND
Clamp', and 'Rising Waveform' are stored as a 'Range' object. Each item in the
Range object is an x, y tuple who's members are a list of floats.

'NA' and 'NC' entries are stored as None.

'[End...]' keywords are not stored.

Parse Results - Section 4 - File Header Information
===================================================

Keywords within the file header are stored in a "fake" section called "header".
Multiple occurrences of multi-line sections, such as 'Source' and 'Copyright'
are merged together. The 'Comment Char' keyword does not appear in parse
output.

    print results.header["File Name"]

Parse Results - Section 5 - Component Description
=================================================

Components are stored as a dict within the 'Component' keyword with each key
representing a component name, and each value representing a component.

Items in the 'Series Pin Mapping' keyword are indexed by the tuple (pin_1,
pin_2).

'Series Switch Groups' are just stored as a list of lists, which each list
starting with the keyword 'on' or 'off'.

Parse Results - Section 6 - Model Statement
===========================================

Models are stored as a dict within the 'Model' keyword with each key
representing a model name, and each value representing a model.

Drain model types are deprecated and replaced by the parser with the associated
sink type.

The 'Rising Waveform' and 'Falling Waveform' sections are stored as a list
of sections. Because the section contains multiple keywords along with waveform
data, the waveform data is stored under the keyword 'waveform'. Additionally,
the keywords 'V_fixture_min' and 'V_fixture_max' are combined with the
'V_fixture' keyword to create a Range.

'Series MOSFET' I-V tables are indexed by their 'Vds' value.

'Test Data' and 'Test Load' are handled the same way as 'Model' and 'Component'
keywords.

Parse Results - Section 6a - Add Submodel Description
=====================================================

'Submodel' keywords are handling in a similar way to 'Model' keywords.

Parse Results - Section 6b - Multi-lingual Model Extensions
===========================================================

Multi-lingual extensions are supported as additional keywords under the
'Component' and 'Model' keywords as well as the additional top level 'External
Circuit' keyword.

The data under the 'Corner' keyword is reorganized so that the 'file_name'
keyword and 'circuit_name' keyword under 'Corner' each contain a Range object.

The 'D_to_A' and 'A_to_D' keywords are stored as dict's indexed by 'd_port'.
Additionally, each parameter is stored as a Range object.

'Portmap' keywords are stored as dict's indexed by 'port'.

Parse Results - Section 6c - Algorithmic Modeling Interface (AMI)
=================================================================

The 'Algorithmic Model' keyword is supported under the 'Model' keyword.
Although parsing of the keyword supported, pybis does not at this time parse
AMI files.

Parse Results - Section 7 - Package Modeling
============================================

The matrices in 'Model Data' are stored as as a numpy matrix. A keyword, 'Pin
Mapping', is added to 'Model Data' that provides a mapping from pin name to
numpy matrix index.

The parser insures that a 'Package Model' contains either 'Model Data' or
section data associated with pins, but not both. In either case, 'Pin Numbers'
is stored as a dict indexed by pin name. In the 'Model Data' case, the value
for each pin is 'None'. In the sections case, the value for each pin is a list
of stubs. A stub can either be a 'Len', 'R', 'L', 'C' IBISNode, or it can be a
list of stubs in the case of a fork.

Parse Results - Section 8 - Electrical Board Description
========================================================

The 'Path Description' section under a 'Begin Board Description' keyword is
stored as a list. Each element in the list can be an IBISNode containing 'Pin',
'Node', or 'Len'. If the IBISNode contains 'Len' it is a stub and may also
contain 'L', 'R', and/or 'C'. An element in the list can also be a list, which
indicates a fork.

Parse Results - Section 11 - EMI Parameters
===========================================

Extra EMI keywords are supported under the 'Component' and 'Model' keywords.

Parse Errors
============

Parse errors throw an Exception along with a parse tree backtrace, which due to
the immaturity of the parser, often does not return helpful data:

    In 'body ' , 'Model BPS2P10F_PU50K' :
    Parsing failed on line 2144: 'Ref                    = 1Mohms'
    Traceback (most recent call last):
      File "pybis.py", line 2148, in <module>
        root = parser.parse(open(sys.argv[1], 'rb'))
      File "pybis.py", line 2019, in parse
        self.parseLine(line)
      File "pybis.py", line 2090, in parseLine
        self.current.parser.fin(self.current)
      File "pybis.py", line 1366, in fin
        .format(model_type, keyword))
    Exception: Type 'i/o' missing required keyword 'Ramp'

In the above backtrace, the error listed is:

    Type 'i/o' missing required keyword 'Ramp'

However, the cause of the error is a misspelling of the 'Rref' keyword. This is
because upon encountering and unknown keyword in a section, the parser assumes
the keyword is contained in a higher level section and so closes the section.
The close function of the section notices that the 'Ramp' keyword is missing
and throws an exception.

Most parse errors will occur when sections are closed. The line number given in
this case will be the line number that cause the section to be closed:

    In 'body ' , 'Model BPS2P10F_PU50K' :
    Parsing failed on line 2785: '[Model]             BPS2P4F_PD50K'
    Traceback (most recent call last):
      File "pybis.py", line 2148, in <module>
        root = parser.parse(open(sys.argv[1], 'rb'))
      File "pybis.py", line 2019, in parse
        self.parseLine(line)
      File "pybis.py", line 2090, in parseLine
        self.current.parser.fin(self.current)
      File "pybis.py", line 1366, in fin
        .format(model_type, keyword))
    Exception: Type 'i/o' missing required keyword 'C_comp'

In this case the Exception is correct, but the line number is misleading. In
both cases, the first line of the backtrace (starting with 'In') can be used to
locate the error.

Performance
===========

Performance of PyBIS is slower than the golden parser (ibischk5) by a factor of
10. Although this is unfortunate, the performance should still be acceptable
for many workloads.

# of lines | ibischk5 | pybis    | factor
79178        0m0.394s   0m3.438s   8.7
9624         0m0.056s   0m0.539s   9.6

Compatibility
=============

Because the IBIS specification is somewhat vague, the definition of what is or
is not a valid IBIS file is typically defined by what can pass though the
golden parser (ibischk5).

Because of this, the highest priority of PyBIS is to accept any files accepted
without errors by ibischk5. A secondary goal is to emit any valid errors or
warnings that the golden parser emits.

Example Code
============

Example code is included in examples/.

models.py - Given an IBIS file as an argument, list the models contained in the
IBIS file:

    ./models.py sample1.ibs
    BIP00F input
    BIPIN15F input
    BPIN15F_PU50K input
    BPIST02F input
    BPIST02F_PU50K input
    BPOZ2F 3-state
    BPOZ4F 3-state
    BPS2P10F_PU50K i/o
    BPS2P4F_PD50K i/o
    BPS2P4F_PU50K i/o
    BT2Z50CX i/o
    BT2Z50CX_PU50K i/o
    BUSB6AU_HIGH_SPEED i/o
    BUSB6AU_LOW_SPEED i/o

Selecting a model then displays the Time based and I-V curves of that model:

    ./models.py sample1.ibs BPOZ2F
    (scipy plots are displayed)

ibs2symdef.py - Convert the components in an IBIS file to a djboxsym symdef
file:

http://www.gedasymbols.org/user/dj_delorie/tools/djboxsym.html

This uses model information to intelligently place pins.

Sample Data
===========

Some sample IBIS files have been collected and are present in samples/.

Installation
============

Do the usual:

    python setup.py install

Future Changes
==============

In the long term, it is desired that PyBIS will expand into a suite of python
based IBIS tools. In the short term, the parser requires incremental changes.
Some of the areas that need improvement are:

    - Improved error messages.
    - Warning messages.
    - Improved compatibility.
    - Performance improvements.
    - Line numbers in parse results.
    - Cleaned up code base.
    - Additional IBIS samples including code test cases.

Some possible future feature ideas include:

    - AMI parsing.
    - IBIS version handling.
    - Folding together of newer and older IBIS fields and features in parse
      output. For example, Vinl appears in 3 different keywords.
    - A GUI based IBIS file viewer/browser.

About

Python based IBIS parser

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages