Skip to main content

PyTCL allows control EDA tools directly from Python that use TCL

Project description

PyTCL

PyTCL allows control EDA tools directly from Python that use TCL.

Features

  • It executes Python method with provided positional arguments directly as TCL procedure For example invocation of Python <object>.<name>(*args) method is like calling TCL procedure <name> {*}${args}
  • Any Python value is converted to TCL value like for example Python list to TCL list
  • Result from invoked TCL procedure is returned as pytcl.TCLValue that can handle any TCL value (that is represented always as string) to Python str, int, bool, float, list, dict, ...
  • TCL error is returned as Python exception pytcl.TCLError
  • High performance and very low (unnoticeable) overhead by using Unix domain sockets for communication between Python and TCL in streamable way (sockets are always open and ready)
  • It allows to create and access TCL variables from Python side. Please see tests/test_tclsh.py for some examples
  • It can work with any EDA tool. Please see tests/test_vivado.py how to use bare PyTCL class for that
  • No external dependencies

Install

pip install pytcl-eda

Examples

Creating new Vivado project:

#!/usr/bin/env python3
from pathlib import Path
from pytcl import Vivado

def main() -> None:
    """Create new Vivado project."""
    hdl_dir: Path = Path.cwd() / "hdl"
    project_dir: Path = Path.cwd() / "my-awesome-project"

    with Vivado() as vivado:
        # See Vivado Design Suite Tcl Command Reference Guide (UG835) for all available Vivado TCL procedures
        # https://docs.amd.com/r/en-US/ug835-vivado-tcl-commands
        vivado.create_project(project_dir.name, project_dir)

        vivado.add_files(hdl_dir / "my_awesome_design.sv")

        synthesis_runs = list(vivado.get_runs("synth_*"))
        implementation_runs = list(vivado.get_runs("impl_*"))

        vivado.launch_runs(synthesis_runs)

        # wait_on_runs was introduced in Vivado 2021.2. For backward compatibility we will use wait_on_run
        # https://docs.amd.com/r/2021.2-English/ug835-vivado-tcl-commands/wait_on_runs
        # Vivado >= 2021.2 can just use: vivado.wait_on_runs(synthesis_runs)
        for run in synthesis_runs:
            vivado.wait_on_run(run)

        vivado.launch_runs(implementation_runs)

        for run in implementation_runs:
            vivado.wait_on_run(run)

        vivado.close_project()

if __name__ == "__main__":
    main()

To use any EDA tool where PyTCL doesn't provide neat helper classes like pytcl.Vivado you can use the pytcl.PyTCL class directly:

#!/usr/bin/env python3
from pathlib import Path
from pytcl import PyTCL

def main() -> None:
    """Create new Vivado project."""
    project_dir: Path = Path.cwd() / "my-awesome-project"

    # PyTCL offers some string placeholders {} that you can use:
    # {tcl}      -> it will insert <pytcl>/execute.tcl
    # {receiver} -> it will insert <pytcl>/receiver.tcl
    # {rx}       -> it will insert /tmp/pytcl-XXXXX/rx.sock
    # {sender}   -> it will insert <pytcl>/sender.tcl
    # {tx}       -> it will insert /tmp/pytcl-XXXXX/tx.sock
    # {args}     -> it will insert '{receier} {rx} {sender} {tx}' in one go
    cmd: list[str] = [
        "vivado",
        "-nojournal",
        "-notrace",
        "-nolog",
        "-mode",
        "batch",
        "-source",
        "{tcl}",
        "-tclargs",
        "{receiver}",
        "{rx}",
        "{sender}",
        "{tx}",
    ]

    with PyTCL(*cmd) as vivado:
        vivado.create_project(project_dir.name, project_dir)

        # Do the same magic that you would normally do in TCL

        vivado.close_project()

if __name__ == "__main__":
    main()

Architecture

stateDiagram-v2
    direction LR
    PyTCL --> rx.sock: send()
    rx.sock --> receiver.py: string
    state tool {
        receiver.py --> execute.tcl: stdin
        execute.tcl --> sender.py: stdout
    }
    sender.py --> tx.sock: NDJSON
    tx.sock --> PyTCL: recv()
  • PyTCL will start new receiver listened on Unix domain socket /tmp/pytcl-XXXX/tx.sock for any incoming NDJSON messages {"result": "<tcl-result>", "status": <tcl-status>} from execute.tcl script file
  • PyTCL will call command line tool (by default tclsh) with execute.tcl script file and arguments receiver.py /tmp/pytcl-XXXX/rx.sock sender.py /tmp/pytcl-XXXX/tx.sock
  • Started execute.tcl will create own listener with Unix domain socket /tmp/pytcl-XXXX/rx.sock to receive incoming TCL expressions from PyTCL
  • PyTCL will start new client and connect to Unix domain socket /tmp/pytcl-XXXX/rx.sock to send TCL expressions with arguments to be evaluated by execute.tcl script file
  • PyTCL will transform any Python method call <object>.<name>(*args) to TCL expression <name> {*}${args}
  • PyTCL will send TCL expression to execute.tcl using Unix domain socket /tmp/pytcl-XXXX/rx.sock
  • execute.tcl will receive TCL expressions from Unix domain socket /tmp/pytcl-XXXX/rx.sock
  • Received TCL expression is evaluated by TCL eval within TCL catch
  • TCL result and status from evaluated TCL expression will be packed into NDJSON message {"result": "<tcl-result>", "status": <tcl-status>}
  • Packed NDJSON message with TCL result and status will be send back to PyTCL
  • PyTCL will return received NDJSON message as pytcl.TCLValue
  • PyTCL will raise a Python exception pytcl.TCLError if received TCL status was non-zero

Development

Create Python virtual environment:

python3 -m venv .venv

Activate created Python virtual environment:

. .venv/bin/activate

Upgrade pip:

pip install --upgrade pip

Install project in editable mode with pytest:

pip install --editable .[test]

Run tests:

pytest

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

pytcl_eda-0.2.1.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

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

pytcl_eda-0.2.1-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file pytcl_eda-0.2.1.tar.gz.

File metadata

  • Download URL: pytcl_eda-0.2.1.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for pytcl_eda-0.2.1.tar.gz
Algorithm Hash digest
SHA256 e3fa21db707e6557889d21994a59e97ddd57e282565a12b1abe28d5f680e800a
MD5 4e65d859153628e71ee7888e8865e05a
BLAKE2b-256 b8e894bdf8133b31e34158ee7877f81ea069672fd71c3d571324387f8ecc769a

See more details on using hashes here.

File details

Details for the file pytcl_eda-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: pytcl_eda-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for pytcl_eda-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0293a14aea3b814ad05aede81501e45c2ed129d4af99b11a8678943ca747989d
MD5 79c741dab11315882c7fcb1ab489cc13
BLAKE2b-256 bc53b442a85f9fff0311c1b9a14e8f1f14073b180dad1444d37943d7247b9ccc

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