Skip to main content

archgraph-layout

Hierarchical architecture diagrams from XML — a Graphviz-style tool built for complex hardware and system diagrams. Instead of a layered (Sugiyama) layout that grows very tall or very wide, archgraph floorplans each subsystem, the way VLSI tools place blocks on a die. The result fits a target aspect ratio, groups blocks by subsystem, and keeps signal flow readable. Wires are routed orthogonally, with real port handling, nets and buses.

python -m archgraph render examples/soc.xml -o soc.svg -o soc.html
  • Pure Python (numpy + scipy). Output: SVG, an interactive HTML viewer (pan/zoom/search/highlight), JSON layout data, and optionally PNG (via Playwright).
  • Deterministic: the same input and seed always give the same drawing.

Installation

Requires Python 3.10 or newer. Install from PyPI after publication:

python -m pip install archgraph-layout

The Python import is archgraph and the command is archgraph:

archgraph --version
archgraph render system.xml -o system.svg -o system.html

For example, save this as system.xml:

<archgraph title="My system">
  <node id="cpu" label="CPU"/>
  <node id="memory" label="Memory"/>
  <edge from="cpu" to="memory"/>
</archgraph>

For optional PNG export, install the extra and Chromium:

python -m pip install "archgraph-layout[png]"
python -m playwright install chromium

The source archive includes the XML examples and reference. Generated gallery previews and development files are excluded from the published packages.


Contents

  1. How the engine works
  2. Command line
  3. Python API
  4. XML reference
  5. Tuning
  6. Examples
  7. Testing

How the engine works

XML ──► parse/expand ──► size blocks ──► auto-cluster huge levels
    ──► hierarchical floorplanning (bottom-up, several passes)
    ──► detailed QP placement + edge alignment (bottom-up, then top-down)
    ──► port sides (router-chosen) ──► orthogonal routing ──► congestion-driven spacing
    ──► nudging ──► labels ──► SVG / HTML / JSON / PNG

Floorplanning (placement). Each subsystem level is a floorplanning problem over its direct children. A child can be a leaf block or a subsystem that was already laid out. Topologies are encoded as sequence pairs and explored by simulated annealing. The cost combines:

term what it measures
area, aspect packing density; deviation from the target width/height (steeper at the top level)
wire weighted Manhattan length between pins: the exact deep port positions inside children
flow edges running against the subsystem's direction (backward edges cost more than sideways ones)
bend connections whose ends cannot be aligned without a bend
crossing / through straight-line crossings, and wires passing through other blocks (routing proxies)
terminal connections leaving the subsystem pull towards the side facing their partner
order repeated instances (core0, core1, …) read in declaration order
hints your guidance (see Layout hints)

Child subsystems contribute several shape variants (natural, square, wide, tall). The annealer picks one per child, and can also mirror a child perpendicular to its flow. Initial states come from a Sugiyama layout (LP layering, barycentre ordering, VPSC coordinates, aspect-driven band wrapping), a spectral (Fiedler) grid order, warm starts from the previous pass, and random states. Tiny levels (≤ 4 blocks) are solved exhaustively. Identical template instances are solved once and drawn identically.

Detailed placement. The annealer gives each level a topology; a convex QP then computes exact coordinates. The QP is solved by gradient projection over a VPSC separation-constraint solver. It straightens wires, compacts, and enforces non-overlap, containment and your hard hints. A greedy HOLA-style pass then adds equality constraints so that nearly straight connections become exactly straight. A top-down pass re-solves every level with the real positions of external partners.

Routing. All wires are routed orthogonally on a sparse non-uniform grid, using an A* search that knows each wire's direction. Costs cover length, bends, crossings, channel sharing, corridor overflow, passing other ports, wall proximity (wires prefer channel centres), turning close to a wall, and crossing subsystem borders. Crossing the border of a subsystem that contains neither end is almost forbidden. Specifics:

  • Ports have a straight escape (about 20px) before the first turn.
  • A first pass routes with floating ports, so each automatic port attaches on the side its wire arrives from.
  • Edges sharing a declared port form one net, drawn as a Steiner tree with junction dots. Buses become trunk trees.
  • PathFinder negotiation rips up and reroutes congested nets.
  • Congestion-driven spacing. Gaps that carry more wires than fit comfortably are widened, overloaded blocks grow, and the layout is re-compacted (same topology) and rerouted.
  • Nudging (VPSC again) spreads overlapping wires into parallel tracks. It orders them to avoid crossings, keeps them clear of blocks and titles, and centres bundles in their corridor. Every port's escape stub is a keep-out zone, so no wire is squeezed in under an arrowhead.
  • Crossings (crossings="hop", the default; or "gap" / "none"). Hops are drawn in a layer above every wire, with a halo in the local background colour, so nothing is ever painted over a hop. Crossings closer together than one hop share a single flat bridge. Each hop bumps to the side where the crossed wire has room (clear of its arrowheads, corners and neighbouring parallel wires). A crossing right next to a corner of the horizontal wire hops sideways on the vertical wire instead. Bit-width markers and edge labels keep clear of crossings.

Command line

archgraph render  FILE.xml [-o OUT.svg|.html|.json|.png ...] [--stats]
                  [--quality draft|normal|high|max] [--aspect 16:9] [--theme dark]
                  [--direction TB] [--seed N] [--set key=value ...]
archgraph validate FILE.xml        # parse, report errors (with line numbers) and warnings
archgraph stats    FILE.xml        # lay out and print quality metrics as JSON
archgraph expand   FILE.xml        # print the XML after templates/loops/includes expand
archgraph FILE.xml -o out.svg      # shorthand for render

--stats reports blocks, aspect, crossings, bends, wire length, overlaps, containment violations, wires through blocks, wire length hugging walls, minimum port escape, flow-consistency counts and timings.

Python API

import archgraph

g = archgraph.build("system.xml", aspect="4:3", quality="high")  # parse + layout + route
archgraph.save(g, "system.svg")        # format by extension: .svg .html .json .png
svg = archgraph.to_svg(g)

g = archgraph.loads(xml_text)            # or step by step
archgraph.layout(g); archgraph.route(g)
for n in g.nodes(): print(n.id, n.x, n.y, n.w, n.h)
from archgraph.quality import metrics; print(metrics(g))

XML reference

See the standalone XML reference for a starter diagram, settings and defaults, nodes and ports, edges and buses, layout hints, styles, templates, loops, includes, and validation guidance.


Tuning

  • Shape: aspect (global) and per-subsystem aspect. The top level weights aspect most.
  • Compactness vs readability: <weights area="0.6" wire="2.4" flow="3" crossing="1.4" through="1.4" bend="1.6" terminal="1.4" order="1.6" aspect="2.2" hint_hard="10" hint_soft="2.5"/>.
  • Effort: quality="high" adds an annealing pass, longer schedules and more spacing iterations.
  • Room for wires: node-spacing, subsystem-padding, edge-spacing, node-margin.
  • Big flat graphs: max-level-items and auto-group="visible" (shows the clusters found).
  • Hard vs soft hints: left-of/above/row/column/order are hard: the floorplanner only considers arrangements that keep them, and a subsystem shape that would break them is never offered to the parent. near/place/anchor are soft preferences.
  • Port sides are chosen from geometry (facing the partner, flow, blocked sides) and then refined by a trial routing pass that may move a port to another side when the wire is clearly better there; sides facing away from the partner are strongly discouraged. Pin a side explicitly with side= on a <port> or from="a@north".

Examples

file shows
examples/basic.xml small starter
examples/soc.xml mobile SoC: big.LITTLE templates, NoC hubs, buses, notes, hints, legend, title block
examples/accelerator_mesh.xml 64-tile mesh accelerator, ~200 blocks (nested repeats, grid, uniform instances)
examples/datacenter.xml spine/leaf fabric, racks, storage, dark theme
examples/automotive.xml zonal E/E architecture, CAN/Ethernet buses, TB flow
examples/fpga_pipeline.xml DSP datapath with mux/register/adder shapes, layered algorithm
examples/flat_network.xml 150+ blocks without subsystems: automatic clustering

Testing

python -m pip install -e ".[dev]"
python -m pytest tests -q

The suite covers the VPSC solver (checked against SLSQP and KKT conditions, including infeasible systems), the XML language, floorplanning and placement invariants (no overlaps, containment, hint satisfaction, aspect), routing invariants (orthogonality, connectivity, no wires through blocks, port escape, clearance), rendering, the CLI, and end-to-end quality metrics for every example.

License and author

MIT License. Copyright (c) 2026 Ellie Hartung. See LICENSE.

For release instructions, see Publishing in the checkout.

Metadata

Release files for archgraph-layout 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for archgraph-layout 1.0.0
File Size Uploaded
archgraph_layout-1.0.0.tar.gz 156.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for archgraph-layout 1.0.0
File Interpreter ABI Platform
archgraph_layout-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 302.5 kB

Release files / archgraph_layout-1.0.0.tar.gz

Download URL archgraph_layout-1.0.0.tar.gz
Size 156.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9ef3b865fa6d7fccbef24c8ca31ffed77fd64062c73945d7c2d0482f135aaeea
BLAKE2b-256 checksum
How to use checksums
a0c46a7d46c25ae178b2aa3cbbdc263b72fc0909079a9502f00d52670352a199
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / archgraph_layout-1.0.0-py3-none-any.whl

Download URL archgraph_layout-1.0.0-py3-none-any.whl
Size 146.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
33b0cdaff6c9ba97c90e04df27bb00b00a25988c69573d2b53adc39acd7fe3b4
BLAKE2b-256 checksum
How to use checksums
8b60fd27f34e597413cfe8afd9697ef0c7be92dc09a721c4cbbdb5cc56940046
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.1

2 release files

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page