Types

The powerful type system is one of the features that make Spade stand out the most compared to contemporary HDLs. For software developers already familiar with Rust, the Spade type system is very similar to that of Rust, to the point where you can skim this section and assume that you’re writing Rust.

Structs

Like most languages, Spade supports structs to encapsulate related values. For example, a struct containing a field named a with type int<8> and b with type bool can be written as:

struct IntAndBool {
    a: Type used to represent signed integers. The generic parameter (<N>) specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
ies the number of bits
, b: Type used to represent 1 bit values }

Structs are initialized as if they are functions. This means you can either do so with positional arguments:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
instance = IntAndBool(0, true);

or with named arguments:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
instance = IntAndBool$(a: 0, b: true);

Like many languages, accessing struct fields is done with . like:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
x = instance.a; let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
y = instance.b;

Tuples

Sometimes, defining a named struct just to group values is overkill, which makes tuples a useful alternative. Tuple types are written as (type1, type2, ...) and values are written as (a, b, ...). As an example, a function that wraps an int<8> and a bool into a tuple can be written as:

Functions together with Entities together with fn and Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. are the basic building blocks of Spade circuits. Unlike fn, entity can contain registers and therefore have state and unlike Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline., they do not have a statically known latency or Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. structure. and Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. are the basic building blocks of Spade circuits. Unlike entities and pipelines, functions have no internal state, they are combinational (pure). example(a: Type used to represent signed integers. The generic parameter (<N>) specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
ies the number of bits
, b: Type used to represent 1 bit values) -> (Type used to represent signed integers. The generic parameter (<N>) specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
ies the number of bits
, Type used to represent 1 bit values) { // ^^^^^^^^^^^^^^ Return a tuple (a, b) // ^^^^^^ Construct the return value }

Tuple elements can be accessed using the . operator:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
a = tup.0; let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
b = tup.1;

though in most cases it is better to use destructuring.

Destructuring

Tuples, structs, and most other types can be destructured to gain access to the inner values. For example, the tuple indexing above can be replaced with:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
(a, b) = tup;

The big advantage of destructuring over indexing is that you cannot forget to account for all fields. If someone adds another field to tup, you will get a compilation error saying that field also needs to be taken into account.

Structs can also be destructured, and like instantiation it can be done with both positional and named arguments:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
IntAndBool(x, y) = instance; let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
IntAndBool$(a: x, b: y) = instance;

Like named arguments, you can also use shorthand notation to bind a field name to a variable of the same name:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
IntAndBool$(a, b) = instance; // Is the same as let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
a = instance.a; let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
b = instance.b;

Destructuring can also be done recursively, for example:

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
(IntAndBool(x, y), z) = instance_and_bool;

Arrays

Arrays too work like most other languages. They are a collection of a fixed number of identically typed values. Array types are written as [T; N] where T is the contained type and N is the number of elements. For example, an array of ten 8-bit integers is written as [int<8>; 10]. For more details on initializing and accessing arrays, see the previous Basic Expressions chapter.

More fancy Types

Beyond these types which are similar to those found in many languages, Spade has some more powerful type system features that are discussed in the next section.