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.0.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.0-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: eda_liberty_parser-0.1.0.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.0.tar.gz
Algorithm Hash digest
SHA256 f66546e9f421f1fb2337cb6fa01458196becf9a99483a034a16bfa61e083501e
MD5 eaba5a59c01b41ce7b4c1b1cf712a5ad
BLAKE2b-256 20aa45b56b291f1ac4b8c573f0ceeee24c7ede165753481f1fbcc0361c1736d4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eda_liberty_parser-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 42e25aa34f6ea6f901fb79d5ecfb5526be4705bb7ff89a1f584e251913cf9abe
MD5 6c91bd04c49aec4973bc692cb734a931
BLAKE2b-256 7d2c20a5f7cc6782a7a220b408dc216707cbeeb4a395b0a12c14a8d11612ef2a

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