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)); }
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
Circuitobject Wireobjects for the inputsCounterWireobjects 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 gatexor_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_1andsappear 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