Filament

A Language for Fearless Hardware Design


Filament is a hardware description language (HDL) that uses types to ensure that your hardware pipelines are composed correctly. Filament’s type system is very different from every other typed HDL: it uses a Rust-inspired type system to reason about structural hazards in your designs and eliminates them at compile-time. For examples of the kinds of problems Filament can solve, take a look at our tutorial.

Features

Composable

Filament uses a new kind of type system to ensure that when you use a module to perform a computation, its timing constraints, like latency and initiation interval are correct. When there are errors, it generates helpful error messages to explain what is wrong with the design!

Efficient

Filament's type system does the heavy lifting to ensure that your modules compose correctly. After that, the compiler erases the types and generates Verilog that is as efficient as hand-written code.

Integrable

Filament makes it easy to integrate black-box Verilog module: just give them a type signature and the compiler will ensure that they are used correctly! Similarly, Filament is easy to integrate in Verilog projects; the compiler generates clean SystemVerilog code that compiles with open-source and commercial tools.

Language

Events & Availability Intervals

Filament's modules are parameterized by events which denote particular clock cycles. Events are used to define the availability intervals of the module's inputs and outputs.

comp Add<'G>(
  left: ['G, 'G+1] 32,
  right: ['G, 'G+1] 32
) -> (out: ['G, 'G+1] 32) {...}

Invocations

In addition to instantiation hardware modules (using the new keyword), Filament uses invocations to to denote when an instance performs some computation. This slight addition enables Filament's powerful type system to reason about structural hazards and imbalanced pipeline paths.

comp main<'G>(
  x: ['G, 'G+1] 32, y: ['G, 'G+1] 32
) -> () {
  A := new Add[32]; // 32-bit adder
  a0 := A<'G>(x, x); // 1st use
  b0 := A<'G+2>(a0.out, y); // 2nd use
}

Event Delays

Each event is associated with a delay that corresponds to the pipeline's initiation interval (II)—the minimum number of clock cycles before the pipeline can process new inputs. Filament's type system checks the implementation of the component and ensures that the delay is correct. This means that your components support the II they promise!

// Processes new inputs every cycle
comp Add<'G:1>(
  left: ['G, 'G+1] 32,
  right: ['G, 'G+1] 32
) -> (out: ['G, 'G+1] 32) {...}

Generative Programming

Filament's guarantees extend to generative programs that generate hardware based on parameters. for loops and if statements can be used to generate hardware and Filament's type system ensures that all valid parameters generate correctly pipelined hardware. This is a really strong property because once your program type checks, you know that all possible instantiations of the program will work!

/* A parameteric shift register */
comp Shift[W, N]<'G:1>(
  in: ['G, 'G+1] W
) -> (
  // delay the signal by N cycles
  out: ['G+N, 'G+N+1] W
) {
  // Tracks the wires b/w registers
  bundle f[N+1]: for<k> ['G+k, 'G+k+1] W;
  f{0} = in;
  for i in 0..N {
      d := new Delay[W]<'G+i>(f{i});
      f{i+1} = d.out;
  }
  out = f{N};
}

Showcase

Using its type system, Filament has enabled us to build reusable, efficient library and designs. Some highlights: If you're building something with Filament, please let us know!

Authors

Filament is being actively developed by Rachit Nigam and the CAPRA group at Cornell University. If you're interested on using or contributing to Filament, please let us know!