Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting Started with RustSFQ

This section walks you through a simple example that demonstrates the basic syntax and core functionality of the RustSFQ library.

We’ll build a half-adder circuit and export it as a SPICE netlist.


Example: Half Adder in RustSFQ

The following Rust program defines a half-adder circuit and generates a corresponding SPICE-format netlist.
We’ll review each part step-by-step below.

use rust_sfq::*;

fn half_adder() -> Circuit<3, 0, 2, 0> {
    let (mut circuit, [a, b, clk], [], [c_out, s_out], []) =
        Circuit::create(["a", "b", "clk"], [], ["c", "s"], [], "HalfAdder");

    let (a1, a2) = circuit.split(a);
    let (b1, b2) = circuit.split(b);
    let (clk1, clk2) = circuit.split(clk);
    circuit.label(&clk1, "clk_1");

    let c = circuit.and(a1, b1, clk1);
    let s = circuit.xor_labeled(a2, b2, clk2, "s");

    circuit.unify(c, c_out);
    circuit.unify(s, s_out);

    return circuit;
}

fn main() {
    let ha = half_adder();
    println!("{}", RsfqlibSpice::generate(&ha));
}
Half Adder Schematic

Project Setup and Import

#![allow(unused)]
fn main() {
use rust_sfq::*;
}

Start by importing all items from the rust_sfq crate. This gives you access to the main types like Circuit, Wire, and backend generators such as RsfqlibSpice.

Creating a New Circuit

#![allow(unused)]
fn main() {
let (mut circuit, [a, b, clk], [], [c_out, s_out], []) =
    Circuit::create(["a", "b", "clk"], [], ["c", "s"], [], "HalfAdder");
}

This call to Circuit::create() initializes a new circuit with:

  • Inputs: a, b, clk
  • Outputs: c, s
  • Name: "HalfAdder"

The second and fourth arguments (empty arrays) represent CounterInputs and CounterOutputs, which are unused in this example.

The returned values include:

  • a mutable Circuit object
  • Wire objects for the inputs
  • CounterWire objects for outputs

Splitting Wires for Fan-Out

#![allow(unused)]
fn main() {
let (a1, a2) = circuit.split(a);
let (b1, b2) = circuit.split(b);
let (clk1, clk2) = circuit.split(clk);
}

Circuit object has split() function, which takes one Wire object and returns two Wire objects.

By calling this function, a SPLIT gate is added to the circuit.

Labeling Wires

#![allow(unused)]
fn main() {
circuit.label(&clk1, "clk_1");
}

You can manually assign a label to any wire, which will appear in the generated netlist.
If you don’t provide a label, a unique name will be automatically assigned.

Creating Gates

#![allow(unused)]
fn main() {
let c = circuit.and(a1, b1, clk1);
let s = circuit.xor_labeled(a2, b2, clk2, "s");
}

Logic gates such as AND and XOR are created by calling methods on the Circuit object.
In this example:

  • and() creates a carry gate
  • xor_labeled() creates a sum gate with a labeled output wire "s"

xor_labeled() is a convenience wrapper for xor() followed by label().

Connecting to Circuit Outputs

#![allow(unused)]
fn main() {
circuit.unify(c, c_out);
circuit.unify(s, s_out);
}

To complete the circuit, connect each gate’s output to the corresponding circuit output using unify().

Exporting the Circuit

fn half_adder() -> Circuit<3, 0, 2, 0> {
    ...
    return circuit;
}
fn main() {
    let ha = half_adder();
    println!("{}", RsfqlibSpice::generate(&ha));
}

The half_adder() function returns a fully constructed Circuit object.
This object is parameterized by the number of inputs, counter inputs, outputs, and counter outputs:
Circuit<3, 0, 2, 0>.

The RsfqlibSpice::generate() function converts the circuit into a SPICE-format netlist based on the RSFQlib.
You can use a different backend (e.g. RsfqlibVerilog) to export in other formats.


Running the Program

You can generate the SPICE netlist by compiling and running the program:

cargo run

This will print the netlist to standard output.

Output: Example SPICE Netlist

Here is the SPICE netlist generated by the example:

.subckt HalfAdder a b clk c s
XSPLIT1 a _XSPLIT1_q1 _XSPLIT1_q2 THmitll_SPLIT
XSPLIT2 b _XSPLIT2_q1 _XSPLIT2_q2 THmitll_SPLIT
XSPLIT3 clk clk_1 _XSPLIT3_q2 THmitll_SPLIT
XAND4 _XSPLIT1_q1 _XSPLIT2_q1 clk_1 c THmitll_AND
XXOR5 _XSPLIT1_q2 _XSPLIT2_q2 _XSPLIT3_q2 s THmitll_XOR
.ends
  • Each logic gate is named sequentially (e.g., XAND4, XXOR5)
  • Wires starting with an underscore (e.g., _XSPLIT1_q1) are automatically generated
  • Labels like clk_1 and s appear as specified in the code

Summary

In this example, you learned how to:

  • Create a new circuit using Circuit::create()
  • Instantiate gates and label outputs
  • Connect gate outputs to declared circuit outputs
  • Export the circuit as a netlist