Skip to main content

A pure-Python parser for Liberty (.lib) files — reads, edits, and writes standard-cell and pad library data for EDA automation workflows

Project description

liberty-parser

A pure-Python parser for Liberty (.lib) cell-library files — the industry-standard format used by EDA tools to describe the timing, power, and interface of standard cells.

CI Python License: MIT

Features

  • Full Liberty grammar — comments, simple attributes, complex attributes, and arbitrarily deep group blocks
  • Round-trip writewrite_liberty() reconstructs the file with the exact original whitespace and formatting
  • In-place editingset_val(), set_vals(), set_LU_matrix(), add_simple(), add_complex(), add_block(), remove_block(), merge_blocks()
  • Hierarchical navigationnavigate() with exact-match or {RE}regex filters, navigate_to_base() to walk up the tree
  • Convenience helpersget_cell_list(), get_pin_list(), map_LU_indexes()
  • Parse from string — no file required; pass a Liberty text block directly
  • Zero required dependencies — only the Python standard library
  • Optional colored output via termcolor
  • CLI included: liberty-parser cells.lib --cell INV_X1 --pins

Installation

pip install eda-liberty-parser                  # no extra dependencies
pip install "eda-liberty-parser[color]"         # adds termcolor for colored output

PyPI Python

Or for development:

git clone https://github.com/rohaansch/liberty-parser
cd liberty-parser
pip install -e ".[dev]"

Quick start

from liberty_parser import LP

lib = LP("cells.lib")

print(lib.get_cell_list())
# ['INV_X1', 'AND2_X1', 'DFFS_X2']

print(lib.get_pin_list(cell="INV_X1"))
# ['A', 'ZN']

# Read a library attribute
time_unit = lib.navigate_single('library', 'time_unit').get_val()
print(time_unit)
# 1ns

Navigation

navigate() accepts a chain of filter strings, one per hierarchy level:

# All cells in the library
cells = lib.navigate('library', 'cell')

# Specific cell by name
inv = lib.navigate_single('library', 'cell:INV_X1')

# Pin direction of a specific pin
direction = lib.navigate_single('library', 'cell:INV_X1', 'pin:ZN', 'direction')
print(direction.get_val())
# output

# Regex filter — find all *_template blocks
for tmpl in lib.navigate('library', '{RE}_template$'):
    print(tmpl.get_val())

navigate_single() returns the first match (or None). navigate_singles() is the fastest variant — stops at the first match at every level.

In-place editing

All edits modify the in-memory dict and are written back with write_liberty():

# Change a simple attribute value
lib.navigate_single('library', 'time_unit').set_val('2ns')

# Or use the two-argument shorthand (nav_to, new_value)
lib.navigate_single('library').set_val('voltage_unit', '1.8V')

# Edit a lookup-table 2-D matrix
cell_rise = lib.navigate_single(
    'library', 'cell:INV_X1', 'pin:ZN', 'timing', 'cell_rise'
)
matrix = cell_rise.get_LU_matrix()
matrix[0][0] = '0.15'
cell_rise.set_LU_matrix(matrix)

# Write back to disk
lib.write_liberty("cells_modified.lib")

Structural edits

library = lib.navigate_single('library')

# Add a new simple attribute
library.add_simple('nom_voltage', '1.8')

# Add a new complex attribute
library.add_complex('operating_conditions', 'typical')

# Remove a cell
cell = lib.navigate_single('library', 'cell:INV_X1')
cell.remove_block()

# Merge another Liberty block into an existing one
lib.navigate_single('library').merge_blocks('extra_cells.lib')

Parsing from a string

No file needed — pass Liberty text directly:

snippet = 'library (mini) { voltage_unit : "1V"; nom_voltage : 1.8; }'
mini = LP(snippet)
print(mini.navigate_single('library', 'nom_voltage').get_val())
# 1.8

Element type predicates

from liberty_parser import is_comment, is_simple_attribute, is_complex_attribute, is_block

for element in lib.navigate('library'):
    if is_block(element):
        print(f"Block: {element.get_val()}")
    elif is_simple_attribute(element):
        print(f"Attr:  {element.get_val()}")

API reference

LP(arg=None)

Argument Behavior
None Create empty LP object
filepath (.lib file) Parse the file
text (Liberty string) Parse the string as a Liberty block
dict Wrap an existing internal dict
LP Share the internal dict of another LP object

Navigation

Method Description
navigate(*filters) Return all matching LP objects
navigate_single(*filters) Return first match at last filter
navigate_singles(*filters) Return first match at every filter (fastest)
navigate_to_base() Walk up to the file root

Getters

Method Description
get_val(nav_to=None) Return value or name string
get_vals(nav_to=None) Return comma-separated value as a list
get_LU_matrix(nav_to=None) Return LU table as a 2-D list
get_type() Return the element type string
get_cell_list() Return all cell names
get_pin_list(cell=None) Return pin names for one or all cells
map_LU_indexes() Return transition/load index map

Setters

Method Description
set_val(nav_or_val, val=None) Set a simple or complex attribute value
set_vals(nav_or_vals, vals=None) Replace comma-separated value list
set_LU_matrix(nav_or_matrix, matrix=None) Replace LU table 2-D matrix

Structural edits

Method Description
add_simple(name, value, insert_ndx=0) Insert a simple attribute
add_complex(type, name, insert_ndx=0) Insert a complex attribute
add_block(lp_block, insert_ndx=0) Insert an LP element
add_blocks(input, insert_ndx=0) Parse and insert multiple elements
remove_block(ndx=None) Remove element at index, or remove self
move_block(from_index, to_index) Reorder elements
merge_blocks(blocks_input) Deep merge another Liberty block

Write & debug

Method Description
write_liberty(out_path) Write parsed dict back to a .lib file
print(indent=0) Pretty-print the internal dict

Command-line usage

liberty-parser cells.lib
liberty-parser cells.lib --cells
liberty-parser cells.lib --cell INV_X1
liberty-parser cells.lib --cell INV_X1 --pins
liberty-parser cells.lib --attr voltage_unit
liberty-parser --version

Or without installing:

python -m liberty_parser cells.lib --cell INV_X1 --pins

Running the tests

pip install -e ".[dev]"
pytest -v

Companion projects

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eda_liberty_parser-0.1.1.tar.gz (18.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eda_liberty_parser-0.1.1-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file eda_liberty_parser-0.1.1.tar.gz.

File metadata

  • Download URL: eda_liberty_parser-0.1.1.tar.gz
  • Upload date:
  • Size: 18.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for eda_liberty_parser-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c7bdae6cee2993a8564e080d1fba68b8cd3a9cef014789f5d0f452c60c45e275
MD5 406cdc69416e89a74d33844b725b66ae
BLAKE2b-256 58edc99e718cc21ea3da76244647dbf47ca28b746a35f4049558a85a89d0fb0e

See more details on using hashes here.

File details

Details for the file eda_liberty_parser-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for eda_liberty_parser-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6433d1c939fbd73b70c92e4d4dab881e78eed87ecd072cacf27de78df025367a
MD5 637e5b9bcda3616d758546e08c491d84
BLAKE2b-256 d29881ca0d0253bc8481ee2eeeef06f8031bd1ed7c50eb1371ef73f94d5a0e29

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page