sdf-parser
A pure-Python parser for Standard Delay Format (SDF) files — the industry-standard format used by EDA tools to back-annotate timing delays and constraints onto digital designs.
Building a Python SDF Parser for EDA Flow Automation — Closing a tooling gap that every EDA engineer eventually runs into.
Features
- Parses
IOPATH,COND,CONDELSE,WIDTH,SETUPHOLD, andRECREM - Single file or directory of SDF files (with cross-file consistency checks)
- Single-cell extraction mode — stops early once the target cell is found
- Zero required dependencies — only the Python standard library
- Optional colored warnings via
termcolor - CLI included:
sdf-parser timing.sdf --cell INV_X1
Installation
pip install eda-sdf-parser # no extra dependencies
pip install "eda-sdf-parser[color]" # adds termcolor for colored warnings
Or for development:
git clone https://github.com/rohaansch/sdf-parser
cd sdf-parser
pip install -e ".[dev]"
Quick start
from sdf_parser import SDFParser
parser = SDFParser()
sdf = parser.read("timing.sdf")
print(repr(sdf))
# SDF(cells=142, files=1, header=['SDFVERSION', 'DESIGN', 'TIMESCALE'])
for entry in sdf.cells["INV_X1"]:
print(entry)
# ['IOPATH', 'A', 'ZN', 2]
# ['COND', "A==1'b0", 'A', 'ZN', 1]
# ['WIDTH', None, 'posedge', 'A', 1]
Parsed entry format
Each entry in sdf.cells["CELLNAME"] is a list whose first element is the
construct keyword:
| Construct | Entry format |
|---|---|
IOPATH |
[IOPATH, pin_1, pin_2, n] |
COND |
[COND, condition, pin_1, pin_2, n] |
CONDELSE |
[CONDELSE, pin_1, pin_2, n] |
WIDTH |
[WIDTH, condition, edge, port, n] |
SETUPHOLD |
[SETUPHOLD, cond_1, edge_1, port_1, cond_2, edge_2, port_2, n] |
RECREM |
[RECREM, cond_1, edge_1, port_1, cond_2, edge_2, port_2, n] |
condition is None when no COND qualifier is present.
n is the number of delay value tuples (e.g. 3 for min/typ/max).
Full example
SDF input:
(CELL
(CELLTYPE "DFFS_X2")
(INSTANCE FF1)
(TIMINGCHECK
(SETUPHOLD (posedge D) (posedge CK) (0.1:0.1:0.1) (0.05:0.05:0.05))
(RECREM (negedge SN) (posedge CK) (0.2:0.2:0.2) (0.1:0.1:0.1))
(WIDTH (posedge CK) (0.3:0.3:0.3))
)
)
Python output:
sdf.cells["DFFS_X2"]
# [
# ['SETUPHOLD', None, 'posedge', 'D', None, 'posedge', 'CK', 2],
# ['RECREM', None, 'negedge', 'SN', None, 'posedge', 'CK', 2],
# ['WIDTH', None, 'posedge', 'CK', 1],
# ]
API reference
SDFParser(path=None)
Create a parser. path sets the default file/directory used by read().
SDFParser.read(path=None, given_cell=None) → SDF
| Argument | Type | Description |
|---|---|---|
path |
str |
.sdf file or directory. Falls back to the constructor path. |
given_cell |
str |
Extract only this cell (case-insensitive). |
Raises ValueError / FileNotFoundError / IOError on bad input.
SDFParser.reset()
Clear internal state to reuse the parser for a different file:
sdf_fast = parser.read("fast.sdf")
parser.reset()
sdf_slow = parser.read("slow.sdf")
SDF object
| Attribute | Type | Description |
|---|---|---|
header_data |
dict |
Header fields (SDFVERSION, DESIGN, TIMESCALE, …) |
cells |
dict[str, list] |
Cell name → list of parsed entries |
files |
list[str] |
All files that contributed to this object |
format_entries(cell) → str
Format a cell's entries as a human-readable multi-line string:
from sdf_parser import format_entries
print(format_entries(sdf.cells["INV_X1"]))
Parsing a directory
When path is a directory every .sdf file inside it is parsed and merged.
Cells found in multiple files are compared; mismatches produce a warning:
sdf = SDFParser().read("sdf_corners/")
print(repr(sdf))
# SDF(cells=142, files=3, header=['SDFVERSION', 'DESIGN', 'TIMESCALE'])
Command-line usage
sdf-parser timing.sdf
sdf-parser timing.sdf --cell INV_X1
sdf-parser timing.sdf --cell INV_X1 --header
sdf-parser sdf_corners/ --header
sdf-parser --version
Or without installing:
python -m sdf_parser timing.sdf --cell INV_X1
Limitations
- Delay values are not parsed — only the count of value tuples is stored.
- Only the constructs listed above are extracted; other SDF keywords are skipped.
- OASIS and binary SDF formats are not supported.
Running the tests
pip install -e ".[dev]"
pytest -v
License
Metadata
Release files for eda-sdf-parser 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| eda_sdf_parser-0.1.2.tar.gz | 10.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| eda_sdf_parser-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.2 kB
Release files / eda_sdf_parser-0.1.2.tar.gz
| Download URL | eda_sdf_parser-0.1.2.tar.gz |
|---|---|
| Size | 10.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
684f73de1333ab09ce908d0848b63407b3aebf568e87b31cbce4b649ea05bd24
|
|
BLAKE2b-256 checksum How to use checksums |
d669162801bf144d39c4f201b2449261c359200b6ab667e9c36022d9041de142
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / eda_sdf_parser-0.1.2-py3-none-any.whl
| Download URL | eda_sdf_parser-0.1.2-py3-none-any.whl |
|---|---|
| Size | 10.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4db310b0aa6f919731962978735f857f54e9206fc8f6d9241b9612f0f955c318
|
|
BLAKE2b-256 checksum How to use checksums |
73aebc053de2e9379f52f8fd309e6678f95ecbe94febb2f81e6fd4e623cf54ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Security for eda-sdf-parser 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.