Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Training materials for learning the [ChipFlow platform](https://build.chipflow.c
## What's included

- **[Creating a Design for Use with the ChipFlow Platform](getting-started-design.md)** — how to create a new design from scratch for the ChipFlow platform
- **[Hard-Macro Builds (`package = "block"`)](block-package.md)** — produce a LEF + Liberty + GDS + blackbox stub for a parent chip, instead of a packaged chip
- **[Using Hard Macros (`load_blackbox_wrapper`)](using-hard-macros.md)** — instantiate NDA / third-party hard macros (or your own block builds) inside an Amaranth design
- **[Wrapping External RTL](wrapping-external-rtl.md)** — integrating existing Verilog or SystemVerilog modules into an Amaranth design (manual `Instance`)
- **[`RTLWrapper` (TOML-based wrapping)](rtl-wrapper.md)** — higher-level wrapper with auto-mapping and sv2v preprocessing
- **[Wrapping CV32E40P](cv32e40p-example.md)** — worked example: wrapping the OpenHW Group RISC-V core with sv2v and `RTLWrapper`
Expand Down Expand Up @@ -37,6 +39,8 @@ chipflow-training/
├── Makefile # Build commands
├── pyproject.toml # Python dependencies
├── getting-started-design.md # How to write a new design
├── block-package.md # Hard-macro / IP block builds
├── using-hard-macros.md # Instantiating hard macros via load_blackbox_wrapper
├── wrapping-external-rtl.md # Wrapping Verilog / SystemVerilog IP (manual Instance)
├── rtl-wrapper.md # TOML-based RTLWrapper reference
├── cv32e40p-example.md # CV32E40P worked example
Expand Down
93 changes: 93 additions & 0 deletions block-package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Hard-Macro Builds (`package = "block"`)

A "block" build produces a **hard-macro deliverable** instead of a packaged chip — LEF, Liberty (`.lib`), GDS, and a blackbox Verilog stub that a parent chip design can instantiate. Use this when you're delivering reusable IP to be integrated into someone else's chip rather than building a standalone chip yourself.

For a normal packaged-chip build, see [Creating a Design for Use with the ChipFlow Platform](getting-started-design.md). For instantiating a block (this build's output, or any third-party hard macro) inside another design, see [Using Hard Macros](using-hard-macros.md).

---

## When to use it

- You want to **ship an IP block** (analog macro, hardened CPU/peripheral, NDA IP) that another team will instantiate in their chip.
- You need a **physical implementation** (placed/routed, with timing models) rather than just RTL.
- You don't want pads, package bringup, or fixed clock/reset/JTAG slot reservations — block builds skip all of that.

If you just want to manufacture a chip, use a chip package (`pga144` etc.) instead.

---

## chipflow.toml

```toml
[chipflow]
project_name = "my_block"

[chipflow.top]
soc = "design.design:MySoC"

[chipflow.silicon]
process = "ihp_sg13g2"
package = "block"

[chipflow.silicon.block]
width = 50 # pin slots on the N and S edges
height = 80 # pin slots on the W and E edges
```

`width` and `height` are **pin-slot counts** — how many signal pins fit along each edge. The backend converts them to physical microns using the process's pin pitch. Make them generous enough for every signal in your design (the build fails if you run out of slots).

## What's different vs a chip build

| | Chip (`pga144`, …) | Block (`block`) |
|---|---|---|
| Pin numbering | Anti-clockwise from top-left | Per-edge `(side, index)` |
| Bringup pins (clock/reset/JTAG/power at fixed slots) | Yes | No — clock and reset go through regular pins; power comes via straps from the parent |
| Pad cells | Yes | No |
| Floorplan | Fixed package size | Sized from `width`/`height` × pin pitch (or auto-promoted to fixed size if the perimeter dominates) |
| Outputs | GDS | GDS + LEF + Liberty `.lib` + blackbox `.bb.v` |

---

## Build outputs

After a successful block submission you can download:

| File | What it is |
|---|---|
| `<design>.gds` | Final layout |
| `<design>.lef` | Abstract view for the parent's place-and-route — pin locations + obstructions, with `USE POWER`/`USE GROUND` PINs at the boundary so the parent connects power by abutment |
| `<design>_typ.lib` | Liberty timing model (typ corner) for the parent's STA |
| `<design>.bb.v` | Blackbox Verilog stub — module declaration + ports + `(* blackbox *)` attribute, no implementation; what the parent's RTL imports |

The stub looks like:

```verilog
(* blackbox *)
module my_block (clk, rst_n, soc_pins_count_0, ...);
input clk;
input rst_n;
output soc_pins_count_0;
// ...
endmodule
```

---

## Submitting

Identical to a chip build:

```bash
CHIPFLOW_ROOT=my_block uv run chipflow pin lock
CHIPFLOW_ROOT=my_block uv run chipflow silicon submit
```

The platform detects `package = "block"` from the lockfile and runs the macro build flow (synth → floorplan → PDN → place → CTS → route → fill → GDS → abstract).

---

## Caveats

- **Clock and reset go through ordinary pins** — there's no fixed `clk`/`rst_n` slot. They're declared like any other I/O in your design and end up on the perimeter wherever pin allocation places them.
- **Power is by abutment.** The block emits M1 followpin stubs at the boundary as VDD/VSS LEF PINs; the parent must abut to those (or run straps over the macro). There are no dedicated power pads.
- **No bringup harness.** JTAG, scan, and other bringup logic that a chip flow inserts automatically is **not** added. If your block needs them, instantiate them in your design.
48 changes: 47 additions & 1 deletion chipflow-toml-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ Required for silicon builds.
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `process` | enum | **Yes** | — | Target manufacturing process |
| `package` | string | **Yes** | — | Package identifier (e.g. `"pga144"`) |
| `package` | string | **Yes** | — | Package identifier (e.g. `"pga144"`, `"block"`) |
| `power` | dict of voltages | No | `{}` | Power domain voltages |
| `debug` | dict of booleans | No | `None` | Debug configuration flags |
| `block` | table | No (Yes when `package = "block"`) | `None` | Per-project block dimensions for hard-macro builds — see [`[chipflow.silicon.block]`](#chipflowsiliconblock) |

**Allowed `process` values:**

Expand All @@ -42,6 +43,51 @@ Required for silicon builds.

---

### `[chipflow.silicon.block]`

Required when `package = "block"`, ignored otherwise. Used for hard-macro deliverables — see [Hard-Macro Builds](block-package.md).

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `width` | integer | **Yes** | — | Pin slots on the N and S edges |
| `height` | integer | **Yes** | — | Pin slots on the W and E edges |

```toml
[chipflow.silicon]
process = "ihp_sg13g2"
package = "block"

[chipflow.silicon.block]
width = 50
height = 80
```

`width`/`height` are pin-slot counts, not microns — the backend translates them using the process's pin pitch.

---

### `[chipflow.silicon.macros]`

Optional. Declares hard macros (NDA SRAMs, vendor IP, PLLs, blocks produced by an earlier `package = "block"` build) for inclusion in the build. See [Using Hard Macros](using-hard-macros.md).

Each entry is keyed by a **logical name** (used from Python as `load_blackbox_wrapper("<logical_name>", ...)`) and points at a `*.blackbox.json` produced by [`macrostrip`](https://github.com/ChipFlow/macrostrip):

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `blackbox` | path | **Yes** | — | Path to a `*.blackbox.json` describing the macro. Relative paths resolve against `CHIPFLOW_ROOT`. |

```toml
[chipflow.silicon.macros.sram_64x64]
blackbox = "vendor/ihp/sram_64x64.blackbox.json"

[chipflow.silicon.macros.pll_core]
blackbox = "vendor/pll/pll_core.blackbox.json"
```

The blackbox JSON itself carries paths to companion artifacts (LEF, Liberty, frame-view or real GDS, Verilog stub), interpreted relative to the JSON's own directory. At submit time those artifacts are packed into `bundle.zip` under `macros/<logical_name>/`.

---

### `[chipflow.simulation]`

| Field | Type | Required | Default | Description |
Expand Down
44 changes: 39 additions & 5 deletions training-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,13 @@ gh auth login

Follow the prompts to authenticate with your GitHub account.

**Important:** After logging in, add the `user` scope (required for ChipFlow to read your email):
**Important:** After logging in, add the `user:email` scope (required for ChipFlow to read your verified email):
```bash
gh auth refresh -h github.com -s user
gh auth refresh -h github.com -s user:email
```

> A later `gh auth refresh` (or VS Code re-auth) without `-s user:email` can silently drop this scope. If a previously working `chipflow auth login` starts complaining about authentication, re-run the command above.

---

## Part 1: Clone and Set Up
Expand Down Expand Up @@ -248,9 +250,26 @@ rm upcounter/pins.lock
CHIPFLOW_ROOT=upcounter uv run chipflow pin lock
```

### Inspecting and rearranging the allocation

After `chipflow pin lock` you can inspect or tweak the result without hand-editing JSON:

```bash
# Show the allocation as a text table (works for any package type)
CHIPFLOW_ROOT=upcounter uv run chipflow pin show

# Render an SVG layout (Quad/Block packages only) and write it to a file
CHIPFLOW_ROOT=upcounter uv run chipflow pin show -f svg -o upcounter-pinout.svg

# Swap two pin assignments — useful for matching a board layout
CHIPFLOW_ROOT=upcounter uv run chipflow pin swap 17 42
```

`pin swap` operates on integer-pin packages (Quad, Block) and refuses to move bringup pins (clock, reset, JTAG, power) — those stay at fixed slots so PCB-level board bringup remains predictable.

### Notes

- Pin assignment is **automatic** — you cannot manually assign specific signals to specific pins.
- Pin assignment is **automatic** — you cannot manually assign specific signals to specific pins, but you can rearrange the result with `chipflow pin swap`.
- The default package is `pga144`, which has 144 total pins. Some are reserved for system use (clock, reset, JTAG, power rails), leaving roughly 120 pins available for your design's I/O. Other packages can be added by request — contact the ChipFlow team.
- Pins are numbered anti-clockwise starting from pin 1 at the top-left corner.
- The `pins.lock` file should be **committed to version control** so that everyone on the team works with the same pinout.
Expand Down Expand Up @@ -311,6 +330,8 @@ After `chipflow silicon prepare`, local build outputs are in:
ls upcounter/build/
```

`chipflow silicon submit` packs the design RTLIL, `pins.lock`, and a `manifest.json` into a single `bundle.zip` next to the RTLIL — that's what gets uploaded to the platform. Useful to know if you're inspecting the build folder or want a self-contained artifact you can replay later.

---

## Part 6: Clean Up
Expand Down Expand Up @@ -345,6 +366,8 @@ make clean
| Command | What it does |
|---------|-------------|
| `chipflow pin lock` | Generate deterministic pin assignments (pins.lock) |
| `chipflow pin show [-f text\|svg] [-o FILE]` | Display the current allocation (SVG for Quad/Block packages) |
| `chipflow pin swap <a> <b>` | Exchange two pin assignments in pins.lock (Quad/Block packages, non-bringup pins) |
| `chipflow silicon prepare` | Synthesise design to RTLIL locally |
| `chipflow silicon submit` | Submit RTLIL to cloud platform for backend build |
| `chipflow silicon submit --wait` | Submit and stream build logs until complete |
Expand Down Expand Up @@ -405,13 +428,24 @@ Other processes may be available on request. If your target process is not yet s

---

## Build modes

| Mode | `package` value | Output | Doc |
|------|----------------|--------|-----|
| Packaged chip | `pga144`, … | GDS for fab | [Creating a Design](getting-started-design.md) |
| Hard macro / IP block | `block` | GDS + LEF + Liberty `.lib` + blackbox `.bb.v` | [Hard-Macro Builds](block-package.md) |

---

## Troubleshooting

### "Authentication failed" or "Could not retrieve email from GitHub"

If chipflow-lib prints `Your gh CLI token is missing the user:email scope`, your `gh` token has lost the scope (commonly after `gh auth refresh` without `-s user:email`, or a VS Code re-auth):

```bash
# Ensure gh has the user scope (required for ChipFlow to read your email)
gh auth refresh -h github.com -s user
# Add the user:email scope back
gh auth refresh -h github.com -s user:email

# Then re-login with ChipFlow
CHIPFLOW_ROOT=upcounter uv run chipflow auth login
Expand Down
Loading