Hierarchy

The digital representation of chips follows a hierarchical flyweight pattern. Hierarchy is used to represent the nested composition of circuit components - here usually called cells. The flyweight pattern is used to efficiently handle large numbers of almost identical cells.

Cells are the definitions of a certain component like a standard-cell or a memory block. Cells can be instantiated as cell instances that are contained in another cell. As an analogy this can be compared to classes and objects in object-oriented programming: Cells are the classes and cell instances the objects. Since cell instances usually differ only very little they can be handled as so-called flyweights. I.e. they can be represented by a reference to the template cell and some additional information such as the location or the nets connected from the outside.

Two traits define the hierarchical structure in LibrEDA: HierarchyBase and HierarchyEdit. The former defines only how a hierarchical structure can be accessed and traversed, the latter defines how it can be constructed and manipulated.

The following diagram illustrates how this composition graph can be traversed using the functions defined by HierarchyBase.

                              each_cell_dependency
                        +-------------------------------+
                        |                               |
                        +                               v
      +---------------------+   each_dependent_cell  +--------------------+
      |  Circuit (Top)      |<----------------------+|  Circuit (Sub)     |
      +---------------------+                        +--------------------+
      |  +               ^  |                        |   ^   +            |
      |  | each_instance |  |                        |   |   |            |
      |  |               |  |                        |   |   |            |
      |  +--+            | parent_cell               |   |   |            |
      |  |  v            |  |                        |   |   |            |
      |  | +-----------+ |  |                        |   |   |            |
 +-------->|Inst1 (Sub)|-+  |                        |   |   |            |
 |    |  | +-----------+    |                        |   |   |            |
 |    |  |                  |                        |   |   |            |
 |    |  +--+               |                        +---|---|------------+
 |    |     v               |                            |   |
 |    |    +-----------+    |  template_cell             |   |
 +-------->|Inst2 (Sub)|+--------------------------------+   |
 |    |    +-----------+    |                                |
 |    |                     |                                |
 |    |                     |                                |
 |    +---------------------+                                |
 |                                                           |
 |                              each_reference               |
 +-----------------------------------------------------------+

Some relations between the above components are worth mentioning. This is loosely taken from the API used in LibrEDA.

  • parent_cell(x): Get the cell where an instance lives in.
  • template_cell(x): Get the type of cell.
  • each_cell_dependency(x): Get all cell templates that are instantiated in a cell x.
  • each_dependent_cell(x): Get all cells that contain instances of cell x.
  • each_instance(x): Get all cell instances inside cell x.
  • each_reference(x): Get all instances of cell x in the whole hierarchy.

Using the functions defined in HierarchyEdit a hierarchical structure can be created as follows:

fn main() {
    use libreda_db::chip::Chip;
    use libreda_db::traits::{HierarchyEdit};
    
    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 an instance inside the top 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.
    );
}