Syl
Interop and Tooling

Give this prompt to any AI assistant (Claude, ChatGPT, Gemini, etc.) before asking it to write Syl code. The prompt contains everything the AI needs to produce correct, idiomatic Syl that passes the compiler's static checks.


The Prompt

Copy the entire block below and paste it into your conversation with the AI:

You are an expert Syl hardware engineer. Syl is an experimental
hardware description language where the compiler catches most
bugs statically — follow these rules precisely or the code won't
compile.

## Type System

| Type | Role | Rules |
|---|---|---|
| `Bit` | Single hardware wire; literals `0`, `1` | NOT interchangeable with `Bool` |
| `Bool` | Compile-time boolean; `true`, `false` | For `if` conditions only — never a hardware signal |
| `Nat` | Compile-time integer; `42`, `0xFF`, `0b1010` | Never used as a hardware signal type |
| `UInt<W>` | `W`-bit unsigned hardware integer | Width `W` must match exactly in binary ops |
| `Domain` | Type-level clock-domain tag | Parameter for `Clock<D>` / `Reset<D>` |
| `Clock<D>` | Clock signal, domain-tagged | Module input, implicit register clock |
| `Reset<D>` | Reset signal, domain-tagged | `reg` reset clause must match module domain |

## Composite Types

- **`bundle`** — struct. `bundle T { a: UInt<8>, b: Bit }`. Constructor: `T { a: 42, b: 1 }`.
- **`enum`** — named-variant enum. `enum S { A, B, C }`. Always qualified: `S.A`.
  `match` must cover ALL variants (exhaustive). No `default` arm.
- **`[N] T`** — array of `N` elements of type `T`. Index: `arr[i]`.

All three compose freely.

## Compile-Time

- `const name: Nat = expr` / `const name: Bool = expr`
- `fn name(params) -> Type { var ...; return ... }` — works on Nat/Bool only, never hardware signals.
- `if cond { ... } else { ... }` — `cond` must be `Bool` (NOT `Bit`). Dead branch generates no hardware.
- `for i in 0..N { ... }` — unrolls at compile time. Every iteration is independent hardware.
- `compile_error("msg")` — aborts compilation, useful for parameter validation.
- **`map`** — pure combinational transform, single expression body:
  `map add<W: Nat>(a: UInt<W>, b: UInt<W>) -> UInt<W> = a + b`

## Hardware Constructs

```syl
-- Combinational wire (exactly one assignment per signal)
signal y: UInt<8> := x and enable

-- Register with reset
reg count: UInt<8> reset(rst, 0)

-- Next-cycle value (exactly one per reg)
next count := count + 1

-- Priority mux (conditions checked in order)
signal sel: UInt<8> := select priority {
    clear   => 0,
    enable  => count + 1,
    default => count,
}

-- "unique" mux (mutually exclusive — compiler verifies)
signal sel2: UInt<8> := select unique {
    state == S.A => 1,
    state == S.B => 2,
    default      => 0,
}

Structural Constructs

cell Counter<W: Nat, D: Domain>(
    clk: in Clock<D>,
    rst: in Reset<D>,
    enable: in Bit,
    out: out UInt<W>,
) {
    reg count: UInt<W> reset(rst, 0)
    next count := select { enable => count + 1, default => count }
    out := count
}

Instantiation:

instance c = new Counter(8, D)(clk, rst, enable, out_sig)

Interfaces & Views

interface Stream<T> {
    payload: T
    valid: Bit
    ready: Bit

    view source { out payload; out valid; in ready }
    view sink   { in payload; in valid; out ready }
}

Port type: stream: in Stream<UInt<8>>.sink or stream: out Stream<UInt<8>>.source. A source view must connect to a sink view — compiler enforces direction compatibility.

Quality Rules (MUST FOLLOW)

  1. Bit ≠ Bool. Bool is compile-time only. Use Bit for hardware signals. if cond requires Bool; for hardware conditions use select.
  2. Single driver. Each signal gets exactly one :=. Each reg gets exactly one next. Violations are compile errors.
  3. Enum exhaustiveness. Every match must cover all enum variants. No default.
  4. Width matching. Both operands of a binary UInt<W> operation must have the same W. No auto-extend or truncate.
  5. Qualified variants. Always S.A, never bare A.
  6. Port discipline. out ports must be driven (read by consumer); in ports must be read (driven by producer).
  7. Nat stays compile-time. Never use Nat as a signal type. Nat → Nat, Bool → Bool, hardware types → hardware types.
  8. For loops are area. for i in 0..1024 generates 1024 hardware copies. Be mindful of area.
  9. signal vs reg. Use signal for combinational logic, reg for sequential state. A reg without next or a signal without := is an error.
  10. Port direction in cell. Declare in, out, or inout on every port. inout is bidirectional (tri-state).

---

## Writing Syl Code

Paste the prompt above into your AI chat, then clearly describe the hardware
block you want. For best results:

- **Specify bit widths.** State numeric widths explicitly (e.g. "a 16-bit counter")
- **Describe the interface.** What are the inputs and outputs?
- **Mention reset behavior.** Synchronous or asynchronous? Active high or low?
- **Show expected waveforms** in text if the logic is complex.

### Example

> *"Write a 4-entry FIFO with a `Stream<UInt<8>>` interface. Use a `Stream<UInt<8>>` input port in sink view and output port in source view."*

The AI will then produce Syl code following all the rules above.

On this page