Netlist

Netlists describe the electrical connections between circuit components. A 'net' is the represenation of a electrical potential, in practice a wire. Circuit components have pins which represent the electrical interface towards the outside. Pins can be connected to a net and a net can be connected to many pins of circuits. This connectivity information is used to fully describe a circuit on the 'netlist' level.

For pins and nets LibrEDA follows the nomenclature used in the Hierarchy. Nets are connected to 'terminals'. A terminal can either be a pin of a circuit (i.e. the interface to the outside of the circuit) or the terminal can be a 'pin instance' . As the name hints, a pin instance is an instantiation of a circuit pin which lives in a circuit instance.

LibrEDA currently defines two traits which allow to access and edit netlist structures.

  • NetlistBase: This trait provides functions to access, query, traverse netlists.
  • NetlistEdit: This trait provides functions to create/remove nets, create/remove pins, connect/disconnect pins and nets. Both traits are tightly linked to the hierarchy traits. A type implementing NetlistBase must also implement HierarchyBase and a type implementing NetlistEdit must also implement HierarchyEdit.

Similar to the hierarchy trait, the netlist traits also define Id types (NetId, PinId, PinInstId). They are handles to the netlist objects and can cheaply be cloned. TerminalId is used to abstract over PinId and PinInstId. It is an enum though.

An example of how to create a simple netlist is shown here:

fn main() {
    use libreda_db::chip::Chip;
    use libreda_db::prelude::*;
    use libreda_db::traits::{HierarchyEdit, NetlistEdit};
    
    let mut chip = Chip::new();
    // Create the cell templates.
    let top_cell = chip.create_cell("MyTopCell".into());
    let sub_cell = chip.create_cell("MySubCell".into());

    // Create pins.
    let top_pin_a = chip.create_pin(&top_cell, "A".into(), Direction::Input);
    let sub_pin_a = chip.create_pin(&sub_cell, "A".into(), Direction::Input);
    
    // Create an instance inside the top cell.
    // The instance will inherit 'pin instances' according to the 'pins'
    // of the template cell.
    let inst1 = chip.create_cell_instance(
        &top_cell, // Create an instance inside this cell.
        &sub_cell, // Create an instance of this template.
        Some("instance_name".into()) // Instances can have a name.
    );
    
    // Create a net. A net must not necessarily have a name.
    // Hence the name is an `Option`.
    let net = chip.create_net(&top_cell, Some("myNet".into()));
    
    // Connect the net to the pin of the top circuit and to the pin instance
    // if the instance of `MySubCell`.
    // This way the signal is passed from the top cell to the sub cell.
    chip.connect_pin(&top_pin_a, Some(&net));
    chip.connect_pin_instance(
        // Get a handle to the pin instance of pin `A` in the instance `inst1`.
        &chip.pin_instance(&inst1, &sub_pin_a),
        Some(&net)
    );
}