Python-first hardware construction and architecture modeling, backed by MLIR, deterministic C++ simulation, and Verilog generation.
pyCircuit provides two complementary Python frontends in one versioned toolchain:
pycircuitconstructs cycle-aware, synthesizable hardware from signals, state, hierarchy, memories, and explicit logical cycles.agentic_circuitmodels architecture-level processes, queues, resources, scheduling, and committed state through ACPy and ACIR.
Both paths converge on verified PYC MLIR when generating hardware. C++ and Verilog therefore share one semantic contract, rather than separate handwritten implementations.
- Cycle-aware by construction. Signal provenance tracks logical cycles, and automatic pipeline balancing lowers to explicit PYC MLIR (Decision 0148).
- One verified contract. Structural and cycle-aware authoring reach the same verified PYC representation; semantics live in the dialect, passes, and verifiers rather than in one backend.
- Deterministic output. Preserved module hierarchy and deterministic generated artifacts.
- Rich data model. Exact-width values, typed structures, queues, tables, and memories.
- Multiple backends. C++ cycle simulation, gfsim architecture simulation, and Verilog generation from one design.
- Reviewable change control. Focused pull-request gates plus a reproducible release closure.
| You want to describe | Install | Import | Primary flow |
|---|---|---|---|
| Ports, signals, registers, memories, pipelines, and synthesizable hardware | pycircuit-hisi |
pycircuit |
Python → PYC → pycc → C++ / Verilog |
| Processes, queues, resources, scheduling, and architecture state | pycircuit-hisi |
agentic_circuit |
Python → acc.py → verified ACIR → acc → C++ / bundle / Verilog |
Read Choose a Frontend for the supported authoring boundaries and examples.
One wheel installs both frontends and both compilers. No compiler build, no LLVM/MLIR checkout, and no CMake are involved:
python3 -m pip install pycircuit-hisiUse Python 3.11 or later. The pycircuit frontend alone runs on 3.10, but the
native bridge bundled for the Agentic Circuit frontend targets the 3.11 stable
ABI, so 3.11+ covers everything in the wheel.
That one install provides:
| Command | What it does |
|---|---|
pycircuit |
Emit PYC MLIR from a Python design, then drive the C++/Verilog backends |
pycc |
Compile PYC MLIR to C++ or Verilog |
acc.py |
Capture ACPy source into verified ACIR |
acc |
Compile verified ACIR to C++, a C++ bundle, or Verilog |
agentic-circuit |
Agentic Circuit workspace, catalog, and diagnostic commands |
import pycircuit, import agentic_circuit, and import _pycircuit_semantics
all resolve from that same install.
Check the install:
pycircuit --help
pycc --help
acc.py --helpSave this as counter.py. It needs nothing from this repository:
from pycircuit import (
CycleAwareCircuit,
CycleAwareDomain,
cas,
mux,
wire_of,
)
def build(m: CycleAwareCircuit, domain: CycleAwareDomain) -> None:
enable = cas(domain, m.input("enable", width=1), cycle=0)
count = domain.signal(width=8, reset_value=0, name="count")
m.output("count", wire_of(count))
# Compute the next value in this logical cycle, then commit it.
count_next = mux(enable, count + 1, count)
domain.next()
count <<= count_next
build.__pycircuit_name__ = "counter"Emit PYC MLIR, then compile it to Verilog:
pycircuit emit counter.py -o counter.pyc
pycc counter.pyc --verilog counter.vcounter.v declares module counter and needs no other input. Swap
--verilog counter.v for --cpp counter.cpp to generate C++ instead.
To build and run a design end to end, add @testbench def tb(t: Tb) to the same
file and use pycircuit build counter.py --out-dir out --target both. That step
also needs CMake, Ninja, and a C++ compiler on the host (--target verilator
and simulation additionally need Verilator).
| Platform | Install |
|---|---|
| macOS (Apple silicon), Windows (x86-64) | python3 -m pip install pycircuit-hisi |
| Linux (x86-64) | python3 -m pip install https://github.com/PTO-ISA/pyCircuit/releases/download/v6.1.0/pycircuit_hisi-6.1.0-py3-none-linux_x86_64.whl |
The Linux wheel is 140 MB, above PyPI's 100 MiB per-file limit, so it is installed from the release URL above until that limit is raised for the project; macOS and Windows install straight from PyPI.
The wheel carries the toolchain and runtime libraries it needs. It requires glibc 2.39 or newer on Linux (Ubuntu 24.04 baseline), macOS 15 or newer, or Windows Server 2022 or newer, and it supports exactly the platforms listed in the SDK release contract.
pycc and acc generate C++ that links against the released runtime. For that,
use the platform SDK archive published with the same release:
pycircuit-sdk-<version>-<platform>.tar.gzplus its.manifest.jsonand.lock.json, or- the matching container artifact
ghcr.io/pto-isa/pyc-tools-<platform>:v<version>.
<platform> is one of linux-x86_64, macos-arm64, or windows-x86_64. The
manifest records the platform's compiler, ABI, minimum OS, and exact file
inventory; the lock records the release identity for a consumer.
The wheel above needs no build. The following source setup is for developing pyCircuit itself and for targets that are not part of a release.
The integrated development setup requires Python 3.11 or later, CMake, Ninja, and LLVM/MLIR 22.1.8. pyCircuit-only frontend use supports Python 3.10 or later.
git clone https://github.com/PTO-ISA/pyCircuit.git
cd pyCircuit
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e "python/semantic-core"
python -m pip install -e ".[dev,docs]"
bash flows/scripts/pyc build
export PYC_TOOLCHAIN_ROOT="$PWD/.pycircuit_out/toolchain/install"Build the counter example with the C++ and Verilog backends:
PYTHONPATH=python/pycircuit/src \
python -m pycircuit.cli build \
examples/pycircuit/basics/counter/tb_counter.py \
--out-dir .pycircuit_out/quickstart/counter \
--target both \
--jobs 8Add the architecture-modeling frontend when needed:
python -m pip install -e "python/agentic-circuit[test]"
agentic-circuit --helpContinue with the Quickstart or the complete installation guide.
Each frontend has one authoring entry point, and both lower to verified PYC before any backend runs.
CycleAwareSignal is the primary authoring model. Compute the next value in the
current logical cycle, call domain.next(), then commit the assignment; the
frontend inserts delay registers wherever cycles must be balanced.
from pycircuit import (
CycleAwareCircuit,
CycleAwareDomain,
build_cycle_aware,
cas,
mux,
wire_of,
)
def build(m: CycleAwareCircuit, domain: CycleAwareDomain, width: int = 8) -> None:
enable = cas(domain, m.input("enable", width=1), cycle=0)
count = domain.signal(width=width, reset_value=0, name="count")
m.output("count", wire_of(count))
# Compute next at cycle 0, then commit after domain.next().
count_next = mux(enable, count + 1, count)
domain.next()
count <<= count_next
build.__pycircuit_name__ = "counter"
print(build_cycle_aware(build, name="counter", width=8).emit_mlir())The full design, testbench, and parameters live in
examples/pycircuit/basics/counter, and the
pyCircuit 6 Tutorial covers testbenches,
hierarchy, memories, and multi-cycle pipelines.
Use Agentic Circuit when a design is better described as typed data moving through queues and atomic rules. Availability, backpressure, reservations, arbitration, and commit are compiler responsibilities, so the Python describes intent rather than hand-built handshakes.
import agentic_circuit as ac
@ac.struct
class Entry:
index: ac.u2
value: ac.u8
def increment(entry: Entry) -> Entry:
return entry.with_fields(value=entry.value + 1)
@ac.rule
def install(entries, incoming):
old = entries[incoming.index]
entries[incoming.index] = increment(incoming)
return old
@ac.system
def transaction_pipeline(incoming: Entry) -> Entry:
entries = ac.table[4, Entry](init=0)
outgoing = install(entries, incoming)
return outgoingEvery @ac.rule is one schedulable atomic transition. Here the Table
replacement and the Queue transfers in install prepare together and publish at
the same tick edge, so backpressure or a state conflict leaves the committed
image unchanged; no reservation, check, or prepare/publish step appears in the
Python.
Runnable state examples, including explicit ac.source() and ac.sink()
capture forms, multi-rule ROB scheduling, and slot ownership, live in
examples/agentic-circuit/state. The
Agentic Circuit and ACIR documentation covers ACPy,
verified ACIR, ACC, QueueGraph, and gfsim, and the
Agent Frontend Guide states the
authoring rules this example follows.
agentic_circuit frontend -> acc.py -> verified ACIR -> acc
|-> gfsim C++ / bundle
`-> PYC -> pycc -> Verilog
pycircuit frontend -> Cycle-Aware Signal -> PYC -> pycc -> pyc6 C++ / Verilog
ACIR remains an architecture-level dialect; PYC remains the shared hardware
contract. The pycircuit and agentic_circuit Python namespaces are separate
and are not compatibility aliases.
| Start here | Purpose |
|---|---|
| Getting Started | Install the toolchain and run the first design |
| Choose a Frontend | Select between pycircuit and agentic_circuit |
| pyCircuit 6 Tutorial | Learn cycle-aware authoring and testbenches |
| Language and API Reference | Look up syntax, APIs, diagnostics, primitives, and PYC IR |
| Architecture | Understand frontends, compiler stages, runtimes, and backends |
| Agentic Circuit and ACIR | Learn ACPy, verified ACIR, ACC, QueueGraph, and gfsim |
| Development Guide | Build, test, contribute, and prepare pull requests |
| Agent Frontend Guide | Choose and apply a Pythonic authoring model for complex circuits |
The tree is organized by responsibility:
python/ Python distributions and shared semantics
compiler/ PYC and ACIR dialects, passes, ACC, and generators
library/ Stable pyCircuit C++ runtime and Verilog implementations
simulator/ gfsim architecture-modeling runtime
docs/ User, architecture, reference, and contributor documentation
examples/ Small supported examples
benchmarks/ Performance-only workloads and harnesses
tests/ Unit, system, integration, MLIR, C++, Verilog, and golden tests
tools/ User-facing and product-maintenance utilities
flows/ Build, CI, gate, and release orchestration
schemas/ Machine-readable contracts, inventories, and registries
packaging/ SDK, archive, and wheel assembly
toolchains/ Pinned compiler and dependency identities
See Repository Layout for the complete
ownership map, including .github/, cmake/, and third_party/. Complete CPU,
NPU, accelerator, SoC, board, ISA, and product-specific testbench sources live
in their owning consumer repositories.
Run the lightweight repository checks first:
pre-commit run --all-files
pytest tests/unit -m unit
python tools/agentic-circuit/check-contracts.py
mkdocs build --strictNative compiler or runtime changes also require the narrowest affected MLIR, C++, simulation, or backend test. The full release matrix runs through the release workflow rather than every pull request.
See Testing and Gates for the exact change-to-gate mapping.
PTO-ISA/pyCircuit is the canonical
source, issue tracker, and release authority. The latest published release is
available from GitHub Releases.
The distribution name is pycircuit-hisi; the Python import remains
pycircuit.
The former standalone Agentic Circuit repository is archived provenance. Its consolidation record is preserved in the historical repository record, not as an active development or compatibility path.
- Contributing guide
- Development workflow
- Review and merge requirements
- Security policy
- Code of conduct
pyCircuit and the integrated Agentic Circuit sources are licensed under the BSD 3-Clause License.
