Metadata-Version: 2.4
Name: ipweave
Version: 0.1.1
Summary: Typed hardware IP construction in Python, emitting readable SystemVerilog
Author: IPweave contributors
License: Apache-2.0 AND BSD-2-Clause
Keywords: hdl,systemverilog,rtl,fpga,asic,eda,ip-xact,systemrdl
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: LICENSE.amaranth.txt
License-File: NOTICE
Provides-Extra: meta
Requires-Dist: jschon~=0.11.1; extra == "meta"
Provides-Extra: vcd
Requires-Dist: pyvcd<0.5,>=0.2.2; extra == "vcd"
Provides-Extra: build
Requires-Dist: jinja2~=3.0; extra == "build"
Provides-Extra: remote
Requires-Dist: paramiko~=2.7; extra == "remote"
Provides-Extra: yosys
Requires-Dist: amaranth-yosys>=0.40; extra == "yosys"
Provides-Extra: ipxact
Requires-Dist: xmlschema>=3; extra == "ipxact"
Provides-Extra: all
Requires-Dist: ipweave[build,ipxact,meta,remote,vcd,yosys]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: ipweave[all]; extra == "dev"
Dynamic: license-file

# IPweave

Typed hardware IP construction in Python, emitting **readable, hierarchical
SystemVerilog**.

IPweave is a complete hardware description environment: a vendored Amaranth language core,
a SystemVerilog printer that preserves the structure you wrote, a numbered rule engine that
refuses the mistakes Verilog makes silent, and the sign-off artefacts an integrator asks
for — IP-XACT, SDC, UPF, register maps and a bill of materials.

```bash
pip install ipweave
```

Python 3.9+. **No mandatory dependencies** — a bare install emits SystemVerilog, runs the
rules and runs the simulator.

## The output is the point

The backend prints from the elaborated fragment tree — statements, hierarchy and names,
before anything is lowered to nets. Nothing is flattened and nothing is renamed.

```python
from ipweave import Module, Signal, unsigned
from ipweave.lib import wiring
from ipweave.lib.wiring import In, Out
from ipweave.strict import wraps


class Counter(wiring.Component):
    """Free-running counter with enable and a wrap pulse."""

    en: In(1)
    count: Out(unsigned(12))

    def elaborate(self, platform):
        m = Module()
        count_q = Signal(unsigned(12))
        with m.If(self.en):
            m.d.sync += count_q.eq(
                wraps(count_q + 1, 12, reason="free-running counter"))
        m.d.comb += self.count.eq(count_q)
        return m
```

```bash
ipweave build counter.py:Counter -o rtl/
```

```systemverilog
// Generated by ipweave 0.1.0 - regenerate, do not edit.
// Free-running counter with enable and a wrap pulse.
// source: counter.py:7  Counter

module counter (
  input  logic        clk, // clock, positive edge
  input  logic        rst, // synchronous reset, active high
  input  logic        en,
  output logic [11:0] count
);

  logic [11:0] count_q;

  always_ff @(posedge clk) begin
    if (rst) begin
      count_q <= 12'h0;
    end else begin
      if (en) begin
        count_q <= 12'(count_q + 13'h1);
      end
    end
  end

  assign count = count_q;

endmodule
```

One file per module. Aligned declarations. The names you chose. A provenance banner naming
the generator line that produced it. `12'(count_q + 13'h1)` because the add really is
thirteen bits wide and the top one really is being dropped — which the language would have
done silently.

A Verilog-2005 backend covers tools that will not read SystemVerilog, so one design reaches
both the newest flow and an older one.

## What it refuses

Write `count_q.eq(count_q + 1)` — the idiom every Amaranth user reaches for, and a silent
truncation of the carry bit — and the build stops:

```
error[IPW-E001] counter.py:16: assignment resizes: target unsigned(12), source unsigned(13)
    note: target declared at counter.py:14
    note: resize explicitly, so the line that loses or invents bits says so
    why: Verilog's implicit extension and truncation is the largest single source of
         silent RTL defects. The language this is built on resizes silently on
         assignment; the strict dialect refuses to, and this pass finds it in code
         that did not use it.
```

**60 rules**, each with a number, a rationale and a severity, applied by **11 analysis
passes**. Profiles (`strict`, `asic`, `fpga`, `legacy`) change severities, never the rule
set. Waivers carry an owner, a reason and an expiry — and an expired waiver fails the
build.

Say which resize you meant, with `ipweave.strict`:

```python
count.eq(zext(part, 12))                              # widen with zero
delta.eq(sext(offset, 16))                            # widen preserving sign
low.eq(trunc(total, 8))                               # the upper bits were not information
count.eq(wraps(count + 1, 12, reason="free-running")) # they were, and dropping them is the point
```

The passes cover clock-domain crossing, reset discipline, combinational loops, latch
inference, bus protocol conformance, register-map consistency, expression depth, power
intent, memory test coverage and unreachable logic.

## Is it the same circuit?

Reading the output cannot tell you. So it is measured: identical stimulus into the Python
simulator and into a vendor simulator running the emitted SystemVerilog, every output
compared as a raw bit pattern, every cycle.

```bash
python tools/cosim.py stress:Stress --cycles 3000
```

```
emitted 2 module(s): lane.sv, stress.sv
compared 3000 cycles x 9 outputs = 27000 samples
the emitted SystemVerilog and the generator agree on every cycle
```

Beyond co-simulation, `ipweave formal` drives bounded model checking through SymbiYosys,
and `ipweave.verif.equiv` proves the emitted netlist equivalent to the synthesised design
with yosys and `eqy`. Functional coverage is sampled in the Python simulator, and a cross
with no expected value reports *unknown* rather than a hundred per cent.

## Sign-off artefacts

One register description produces the C header, the SystemRDL, the IP-XACT, the UVM
register abstraction layer, the documentation and the RTL, so they cannot disagree.

Timing intent is written where the design is written and emitted as SDC. Power intent is
emitted as UPF, following IEEE 1801. Design-for-test covers the 1149.1 TAP state machine,
1687 reconfigurable networks, scan intent and memory BIST coverage.

Seventeen command-line verbs, each with `--json`: `audit` collects what an integrator asks
for, `bom` lists what a design is built from, `describe` emits IP-XACT, `trace` follows a
signal through the hierarchy, and `serve` exposes the whole set over JSON-RPC for tooling.

## Targets

**9 platforms** — AMD (Xilinx), Altera (Intel), Lattice, Gowin, Efinix, Microchip, and a
vendor-independent ASIC target that produces a handoff rather than a bitstream. **196
boards**, each carrying its pinout, its toolchain and where its definition came from.

```bash
ipweave platforms          # what each toolchain has been validated against
ipweave boards --vendor Lattice
```

The platform table records which toolchains IPweave has actually built against and which it
has not, because a target nobody has run is not a target that works.

## The IP catalogue

**20 blocks**, each with a stated contract: arbiters, crossbars, stream FIFOs, skid
buffers, pipeline stages, register files, content-addressable memory, multipliers,
dividers, prefix networks, funnel shifters and clock-domain crossings.

```bash
ipweave catalogue
```

## The vendored language

The Amaranth language is vendored in full — its module system, standard library, simulator,
build system and existing backends — under a recorded patch discipline.
`ipweave/_vendor.json` holds the upstream commit and a digest of every file, four declared
patches carry a reason each, and `python tools/vendor.py diff <amaranth-checkout>` replays
the transform against a fresh upstream so an upgrade is something you read rather than
merge.

The **syntax is unchanged** — shapes, operators, `m.d.sync +=`, `m.If`/`m.FSM`,
`lib.wiring`, `lib.data`, `lib.memory`, the simulator.
[tests/test_language_surface.py](tests/test_language_surface.py) is the short statement of
that promise, and the vendored suite is the long one.

Two things moved, because the package layout is IPweave's:

| Amaranth | IPweave |
| --- | --- |
| `amaranth.back` | `ipweave.emit`, alongside `ipxact`, `sdc` and `upf` |
| `amaranth.cli` | `ipweave.cli` is IPweave's; the old one is `ipweave._legacy_cli` |

Everything else is `amaranth` → `ipweave`.

## Testing

```
2494 tests
  1146  the vendored language, unchanged
  1348  the printer, the rules, the passes, the catalogue, the platforms, the boards,
        the register layer, verification, design-for-test and the command line

Verible lint clean · Questa vlog -lint clean · co-simulation exact
```

`python tools/gate.py` runs every invariant as one thing — the suite, the vendoring
discipline, the rule rationales, rule coverage, the dependency boundary, attribution and
the installation self-test — and fails when a check does not pass **or cannot run**.

## Licence

Apache-2.0 for IPweave's own code. The vendored Amaranth language is BSD-2-Clause, and the
board definitions carry the licences of the projects they came from. See [LICENSE](LICENSE),
[LICENSE.amaranth.txt](LICENSE.amaranth.txt),
[LICENSE.litex-boards.txt](ipweave/board/LICENSE.litex-boards.txt) and [NOTICE](NOTICE) —
the last names exactly which files come from where.

The board set is drawn from **amaranth-boards** and **litex-boards**, re-expressed in
IPweave's own definition format rather than copied, so that every board states its pinout,
its toolchain and its origin in one place.

Amaranth is developed at [amaranth-lang.org](https://amaranth-lang.org). LiteX and
litex-boards are developed by [Enjoy-Digital](https://github.com/enjoy-digital) and the
LiteX-Hub community. This project is not affiliated with either.
