# Cheatsheet / Reference

### Installation and Setup

#### Package Installation

```bash
opam install hardcaml ppx_hardcaml hardcaml_waveterm
opam install hardcaml_c hardcaml_verilator hardcaml_step_testbench
```

#### Project Structure

```
project/
├── src/
│   ├── interfaces.ml    (* Interface definitions *)
│   ├── components/      (* Reusable components *)
│   ├── top.ml          (* Top-level module *)
│   └── utils.ml        (* Utility functions *)
├── test/
│   ├── unit_tests.ml   (* Unit tests *)
│   └── integration_tests.ml
└── bin/
    └── main.ml   (* RTL Code Generation *)
```

### Core Concepts and Fundamentals

#### What is Hardcaml?

**Hardcaml** is an embedded hardware design domain-specific language (DSL) implemented in OCaml by Jane Street. It provides **low-level control** over hardware while abstracting away tedious aspects of traditional HDLs like Verilog/VHDL.

#### Key Design Principles

* **Full Control DSL**: Direct instantiation of hardware primitives (registers, memories, multiplexers)
* **Type Safety**: OCaml's type system prevents connection errors and width mismatches
* **Fast Elaboration**: Circuit construction happens entirely within OCaml at elaboration time
* **Embedded Approach**: No secondary abstraction layers—purely OCaml

#### Graph-Based Representation

Hardcaml represents circuits as **directed graphs** where:

* **Nodes** = hardware operations (registers, logic gates, arithmetic)
* **Edges** = signal connections
* **Cycles** = supported via wires for feedback loops

### Signal Types and Operations

#### Primary Signal Type

```ocaml
type Signal.t  (* Fundamental building block *)

(* Signal creation *)
let a = Signal.of_int ~width:8 42          (* 8-bit constant *)
let b = Signal.input "data_in" 16          (* 16-bit input port *)
let c = Signal.wire 4                      (* 4-bit wire *)

(* Width operations *)
let width_of_a = Signal.width a            (* Query width *)
let resized = Signal.uresize a ~width:10   (* Resize to 10 bits *)
```

#### Bits vs Signals

* **`Bits.t`**: Concrete values for simulation and testing
* **`Signal.t`**: Abstract representation for circuit description

#### Basic Operations

```ocaml
(* Arithmetic *)
let sum = a +: b          (* Addition (same width) *)
let sum_const = a +:. 10  (* Signal + constant *)
let diff = a -: b         (* Subtraction *)
let prod = a *: b         (* Multiplication *)

(* Signed vs unsigned *)
let signed_sum = a +:+ b     (* Signed addition *)
let unsigned_sum = a +: b    (* Unsigned addition *)

(* Bitwise operations *)
let and_result = a &: b      (* Bitwise AND *)
let or_result = a |: b       (* Bitwise OR *)
let xor_result = a ^: b      (* Bitwise XOR *)
let not_result = ~: a        (* Bitwise NOT *)

(* Comparisons *)
let eq = a ==: b            (* Equality *)
let lt = a <: b             (* Less than *)
let gte = a >=: b           (* Greater than or equal *)

(* Multiplexers *)
let mux_result = Signal.mux2 select a b    (* if select then a else b *)
let mux_multi = Signal.mux select_signal [a; b; c; d]

(* Bit selection *)
let upper_bits = Signal.select a ~hi:7 ~lo:4    (* Select bits 7-4 *)
let bit_slice = a.:(7, 4)                       (* Infix syntax *)
```

### Module Definitions and Interfaces

#### Interface Pattern (ppx\_deriving\_hardcaml)

```ocaml
module I = struct
  type 'a t = {
    clock : 'a;
    reset : 'a;
    enable : 'a;
    data : 'a; [@bits 8]
  } [@@deriving sexp_of, hardcaml]
end

module O = struct
  type 'a t = {
    ready : 'a;
    result : 'a; [@bits 16]
  } [@@deriving sexp_of, hardcaml]
end

let create (inputs : Signal.t I.t) : Signal.t O.t =
  let { I.clock; enable; data } = inputs in
  let processed_data = data +: (Signal.of_int ~width:8 1) in
  let result = Signal.reg (Signal.Reg_spec.create ~clock ()) enable processed_data in
  { O.ready = enable; result }
```

#### Interface Attributes

```ocaml
type 'a t = {
  signal : 'a; [@bits 6]                    (* Signal width *)
  signal_list : 'a list; [@length 2]        (* List length *)
  signal_array : 'a array; [@length 3] [@bits 7]  (* Array with bit width *)
  named_signal : 'a [@rtlname "custom_name"]       (* Custom RTL name *)
} [@@deriving sexp_of, hardcaml]
```

#### Parameterized Modules with Functors

```ocaml
module type Config = sig
  val data_width : int
  val addr_width : int
end

module Make (C : Config) = struct
  module I = struct
    type 'a t = {
      data : 'a; [@bits C.data_width]
      addr : 'a; [@bits C.addr_width]
    } [@@deriving sexp_of, hardcaml]
  end
  
  let create inputs = (* implementation *)
end
```

### Combinational Logic Constructs

#### Adder Example

```ocaml
module Adder = struct
  module I = struct
    type 'a t = {
      a : 'a; [@bits 8]
      b : 'a; [@bits 8]
      cin : 'a;
    } [@@deriving sexp_of, hardcaml]
  end

  module O = struct
    type 'a t = {
      sum : 'a; [@bits 8]
      cout : 'a;
    } [@@deriving sexp_of, hardcaml]
  end

  let create (i : _ I.t) : _ O.t =
    let result = i.a +: i.b +: (zero 7 @: i.cin) in
    { O.sum = select result ~high:7 ~low:0;
      cout = select result ~high:8 ~low:8 }
end
```

#### Tree Operations

```ocaml
(* Tree adder for multiple inputs *)
let tree_adder inputs =
  Signal.tree ~arity:2 ~f:(+:) inputs

(* Tree reduction *)
let tree_and inputs =
  Signal.tree ~arity:2 ~f:(&:) inputs
```

### Sequential Logic (Registers, Memories, State Machines)

#### Register Creation

```ocaml
(* Register specification *)
let reg_spec = 
  Signal.Reg_spec.create 
    ~clock 
    ~reset 
    ~clear 
    ()

(* Basic register *)
let reg_out = Signal.reg reg_spec enable data_in

(* Register with feedback *)
let counter = Signal.reg_fb reg_spec ~enable ~w:8 (fun d -> d +:. 1)
```

#### Memory Primitives

```ocaml
(* Basic memory *)
let memory_out = Signal.memory size ~write_port ~read_address

(* RAM with read/write ports *)
let ram_out = Signal.ram_wbr 
  ~write_port:{ write_clock; write_address; write_data; write_enable }
  ~read_port:{ read_clock; read_address; read_enable }
  size

(* Multi-port memory *)
let memory = multiport_memory ~clock
  ~write_ports:[{
    write_clock = clk;
    write_enable = we;
    write_address = addr;
    write_data = data;
  }]
```

#### State Machines with Always DSL

```ocaml
module States = struct
  type t = 
    | Idle
    | Processing
    | Done
  [@@deriving sexp_of, compare, enumerate]
end

let create_state_machine (inputs : Signal.t I.t) =
  let open Signal.Always in
  let sm = Always.State_machine.create (module States) ~enable:inputs.enable in
  let counter = Always.Variable.reg ~width:8 spec in
  
  compile [
    sm.switch [
      Idle, [
        when_ inputs.start [
          sm.set_next Processing;
          counter <-- zero 8;
        ];
      ];
      Processing, [
        counter <-- (counter.value +:. 1);
        when_ (counter.value ==:. 100) [
          sm.set_next Done;
        ];
      ];
      Done, [
        sm.set_next Idle;
      ];
    ]
  ]
```

### Simulation and Testing

#### Basic Simulation

```ocaml
(* Create simulator *)
let sim = Cyclesim.create (Circuit.create_exn ~name:"test" outputs)

(* Drive inputs and simulate *)
let inputs = Cyclesim.inputs sim
let outputs = Cyclesim.outputs sim
inputs.clock := Bits.vdd;
inputs.data := Bits.of_int ~width:8 42;
Cyclesim.cycle sim;
let result = !(outputs.result)
```

#### Expect Test with Waveforms

```ocaml
let%expect_test "counter test" =
  let sim = create_counter_sim () in
  let waves, sim = Waveform.create sim in
  (* simulation steps *)
  for i = 0 to 5 do
    Cyclesim.cycle sim
  done;
  Waveform.print ~display_height:12 ~display_width:70 waves;
  [%expect {|
    ┌Signals────────┐┌Waves──────────────────────────────────────────────┐
    │clock          ││┌───┐   ┌───┐   ┌───┐   ┌───┐   ┌───┐   ┌───┐   ┌──│
    │enable         ││    └───┘   └───┘   └───┘   └───┘   └───┘   └───┘  │
    │count     3    ││────────┬───────────────────────────────────────────│
    │               ││  000   │  001   │  010   │  011   │  100   │  101 │
    └───────────────┘└───────────────────────────────────────────────────┘
  |}]
```

#### High-Performance Simulation Backends

```ocaml
(* Hardcaml_verilator - Ultra-high speed *)
let verilator_sim = Hardcaml_verilator.create circuit

(* Hardcaml_c - C-based simulation *)
let c_sim = Hardcaml_c.create circuit

(* All use same API as standard Cyclesim *)
```

### Synthesis and Compilation

#### RTL Generation

```ocaml
(* Verilog generation *)
let () =
  let circuit = Circuit.create_exn ~name:"my_design" Top.create in
  Hardcaml.Rtl.Verilog.print ~output_file:"design.v" circuit

(* VHDL generation *)
let () =
  let circuit = Circuit.create_exn ~name:"my_design" Top.create in
  Hardcaml.Rtl.Vhdl.print ~output_file:"design.vhd" circuit
```

#### Circuit Creation

```ocaml
let circuit = 
  let module Circuit = Hardcaml.Circuit.With_interface(Top.I)(Top.O) in
  Circuit.create_exn ~name:"top_level" Top.create
```

### Common Patterns and Idioms

#### Pipeline Pattern

```ocaml
let pipeline_stage ~spec input =
  let stage1 = reg spec ~enable:vdd (process_stage1 input) in
  let stage2 = reg spec ~enable:vdd (process_stage2 stage1) in
  let stage3 = reg spec ~enable:vdd (process_stage3 stage2) in
  stage3
```

#### Counter Pattern

```ocaml
let counter ~clock ~clear ~enable count_to =
  let reg_spec = Signal.Reg_spec.create ~clock ~clear () in
  let counter_reg = Signal.wire (Signal.width count_to) in
  let counter_next = Signal.mux2 
    (counter_reg ==: count_to) 
    (Signal.of_int ~width:(Signal.width count_to) 0)
    (counter_reg +:. 1) in
  Signal.assign counter_reg (Signal.reg reg_spec enable counter_next);
  counter_reg
```

#### FIFO Pattern

```ocaml
let fifo ~clock ~clear ~write_enable ~read_enable ~write_data ~depth =
  let addr_width = Int.ceil_log2 depth in
  let mem = Signal.memory depth ~write_port:{
    write_clock = clock;
    write_enable = write_enable;
    write_address = write_addr;
    write_data = write_data;
  } in
  mem ~read_address:read_addr
```

### Error Handling and Debugging

#### Width Validation

```ocaml
(* Compile-time width checking *)
let safe_add a b =
  if Signal.width a <> Signal.width b then
    failwith "Width mismatch"
  else
    a +: b
```

#### Assertion-based Debugging

```ocaml
let counter ~spec ~enable ~clear =
  let count = reg spec ~enable ~clear (count +:. 1) in
  (* Add assertion for overflow detection *)
  assert (count <:. 256);
  count
```

#### Interactive Debugging

```ocaml
let debug_circuit () =
  let sim = Cyclesim.create ~config:Cyclesim.Config.trace_all circuit in
  let waves, sim = Waveform.create sim in
  (* Run simulation *)
  for i = 0 to 100 do
    Cyclesim.cycle sim
  done;
  (* Launch interactive viewer *)
  Hardcaml_waveterm_interactive.run ~wave_width:5 ~signals_width:30 waves
```

### Performance Considerations

#### Memory Usage Optimization

```ocaml
(* Use appropriate memory primitives *)
let efficient_memory = Signal.memory ~size:1024 (* for inference *)

(* FIFO for streaming *)
let streaming_fifo = Signal.fifo ~depth:32 ~write_port ~read_port
```

#### Timing Optimization

```ocaml
(* Tree structures for critical paths *)
let tree_adder inputs =
  Signal.tree ~arity:2 ~f:(+:) inputs

(* Pipeline critical paths *)
let pipelined_mult a b =
  let spec = Signal.Reg_spec.create ~clock () in
  let stage1 = Signal.reg spec ~enable:vdd (a *: b) in
  let stage2 = Signal.reg spec ~enable:vdd (stage1 +:. offset) in
  stage2
```

### Code Examples for Major Concepts

#### FIR Filter

```ocaml
let fir_filter coeffs data_in ~clock ~enable =
  let reg_spec = Signal.Reg_spec.create ~clock () in
  let shift_reg = List.init (List.length coeffs) ~f:(fun i ->
    Signal.reg reg_spec enable 
      (if i = 0 then data_in else List.nth_exn shift_reg (i-1))
  ) in
  let products = List.map2_exn coeffs shift_reg ~f:(fun coeff data ->
    Signal.of_int ~width:16 coeff *: data
  ) in
  Signal.tree ~arity:2 products ~f:(+:)
```

#### Linear Feedback Shift Register (LFSR)

```ocaml
let lfsr ~width ~taps ~clock ~enable =
  let reg_spec = Signal.Reg_spec.create ~clock () in
  let state = Signal.wire width in
  let feedback = List.fold taps ~init:(Signal.of_int ~width:1 0) ~f:(fun acc tap ->
    acc ^: (Signal.select state ~hi:tap ~lo:tap)
  ) in
  let next_state = Signal.concat_msb [Signal.select state ~hi:(width-2) ~lo:0; feedback] in
  Signal.assign state (Signal.reg reg_spec enable next_state);
  state
```

### Quick Reference Syntax

#### Essential Operations

```ocaml
(* Constants *)
let zero_8 = Signal.of_int ~width:8 0
let ones_8 = Signal.of_int ~width:8 255
let vdd = Signal.vdd
let gnd = Signal.gnd

(* Arithmetic *)
let add = a +: b      (* Addition *)
let sub = a -: b      (* Subtraction *)
let mul = a *: b      (* Multiplication *)
let add_const = a +:. 5  (* Add constant *)

(* Logical *)
let and_op = a &: b   (* Bitwise AND *)
let or_op = a |: b    (* Bitwise OR *)
let xor_op = a ^: b   (* Bitwise XOR *)
let not_op = ~: a     (* Bitwise NOT *)

(* Comparison *)
let eq = a ==: b      (* Equal *)
let neq = a <>: b     (* Not equal *)
let lt = a <: b       (* Less than *)
let lte = a <=: b     (* Less than or equal *)
let gt = a >: b       (* Greater than *)
let gte = a >=: b     (* Greater than or equal *)

(* Bit manipulation *)
let sel = a.:(7, 0)   (* Select bits 7 to 0 *)
let concat = a @: b   (* Concatenate *)
let select = Signal.select a ~hi:7 ~lo:0
```

#### Register and Memory

```ocaml
(* Register *)
let reg = Signal.reg spec ~enable data

(* Memory *)
let mem = Signal.memory size ~write_port ~read_address

(* State machine *)
let sm = Always.State_machine.create (module States) ~enable
```

### Best Practices and Conventions

#### Code Organization

1. **Separate interfaces from implementations**
2. **Use modules for logical grouping**
3. **Keep create functions pure and deterministic**
4. **Use descriptive names for signals and modules**

#### Type Safety

```ocaml
(* Custom scalar types for different domains *)
module Types = struct
  module Price = Types.Scalar(struct let width = 32 end)
  module Quantity = Types.Scalar(struct let width = 16 end)
end
```

#### Testing Strategy

1. **Write unit tests for all combinational logic**
2. **Use property-based testing with hardcaml\_verify**
3. **Test edge cases and boundary conditions**
4. **Include waveform verification in tests**

#### Naming Conventions

* Use `snake_case` for signal names
* Prefix with `i_` for inputs, `o_` for outputs
* Use meaningful names that describe the signal's purpose

### Advanced Features and Techniques

#### Hierarchical Design

```ocaml
let create ~scope (i : _ I.t) : _ O.t =
  let module Hierarchy = Hierarchy.In_scope (I) (O) in
  Hierarchy.hierarchical ~scope ~name:"module_name" (fun _scope ->
    (* implementation *)
  )
```

#### Custom Types

```ocaml
module Price_in_usd = struct
  type 'a t = 'a [@@bits 32] [@@deriving sexp_of, hardcaml]
  
  let create = Signal.of_int ~width:32
  let is_positive price = price >:. 0
end
```

#### Verification and Formal Methods

```ocaml
(* SAT-based verification *)
let verify_adder_properties () =
  let verify_commutative = 
    Verify.prove (fun a b -> (a +: b) ==: (b +: a)) in
  let verify_associative = 
    Verify.prove (fun a b c -> (a +: (b +: c)) ==: ((a +: b) +: c)) in
  (* Results in SAT/UNSAT *)
```

### Ecosystem Libraries

#### Core Libraries

* **hardcaml\_circuits**: Arbiters, multipliers, sorting networks, DSP
* **hardcaml\_fixed\_point**: Fixed-point arithmetic with rounding/overflow control
* **hardcaml\_verify**: SAT-based formal verification tools

#### Simulation Libraries

* **hardcaml\_verilator**: Ultra-high speed simulation using Verilator
* **hardcaml\_c**: C-based simulation for improved performance
* **hardcaml\_waveterm**: ASCII waveform visualization
* **hardcaml\_step\_testbench**: Monadic testbench API

#### Xilinx Libraries

* **hardcaml\_xilinx**: Xilinx-specific FPGA components
* **hardcaml\_xilinx\_components**: Tool to generate OCaml from Xilinx libraries

#### Integration Libraries

* **hardcaml\_of\_verilog**: Import Verilog designs into Hardcaml

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ocamlstreet.gitbook.io/hardcaml-wiki/hardcaml/cheatsheet-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
