User Guide

Basic Operation

CharLib runs analog simulation of the configured cells to determine their electrical properties. The overal flow is shown in the figure below.

../_images/flow_block_diagram.svg

To run characterization, you must provide:

  1. SPICE netlists of the cells to be characterized (ideally with extracted parasistics)

  2. Analog transistor models from your PDK

  3. A YAML configuration file

Typically the first two items are provided by your foundry as part of the PDK. The third item tells CharLib how to process the SPICE netlists and transistor models. Using CharLib basically boils down to constructing a YAML file detailing your cells and characterization conditions.

Note

See YAML configuration examples for more information on configuring CharLib.

We have also created a video guide that walks through the process of installing CharLib, creating a configuration file, and characterizing a cell. You can watch that video here on YouTube.

Running CharLib

To interact with CharLib’s command line interface, execute:

charlib <command>

CharLib supports the following commands:

  • run: characterize cells using an existing configuration file

  • compare: (experimental) compare a liberty file against a benchmark “golden” liberty file

  • generate_functions: (experimental) generate test vectors for a particular function

Note

Commands marked with (experimental) may or may not be functional in any given release of CharLib.

Usage

charlib --help

will display lots of useful information. You can also run charlib <command> --help to show usage information for a particular command.

Running characterization

To characterize a standard cell library with CharLib, execute:

charlib run <path_to_library_config>

<path_to_library_config> may be either a path directly to the YAML configuration file, or to a directory containing a configuration file. If <path_to_library_config> is a directory, CharLib recursively searches the specified directory for a YAML file containing a valid cell library configuration. Once a configuration is identified, CharLib characterizes each cell included in the configuration file.

Optional arguments for charlib run include:

  • --output <output>: place characterization results in the specified <output> directory.

  • --jobs <jobs>: specify the maximum number of threads to use for characterization.

  • --filter <filters>: only characterize cells whose names match the regex pattern given in <filters>.

More information about optional arguments can be found by running charlib run --help.

YAML configuration examples

The examples in this section can be run after installing CharLib and downloading the corresponding standard cells.

To download the OSU350 cells and models:

1#! /usr/bin/env bash
2
3export OSU035_COMMIT="b36db529c2dff117e1fbead561bf792ec866e1cb"
4mkdir -p osu350/spice
5mkdir -p osu350/models
6curl -fsSL --retry 3 https://raw.githubusercontent.com/stineje/MOSIS_SCMOS/$OSU035_COMMIT/latest/cadence/lib/ami035/signalstorm/osu035_stdcells.sp > osu350/spice/osu035_stdcells.sp
7curl -fsSL --retry 3 https://raw.githubusercontent.com/stineje/MOSIS_SCMOS/$OSU035_COMMIT/latest/cadence/lib/ami035/lib/ami035.m > osu350/models/ami035.m
8curl -fsSL --retry 3 https://raw.githubusercontent.com/stineje/CharLib/refs/heads/main/test/pdks/osu350/fix_hspice_models.patch > osu350/fix_hspice_models.patch
9patch -s osu350/models/ami035.m osu350/fix_hspice_models.patch

To download the gf180mcu OSU 9t cells and models:

1#! /usr/bin/env bash
2
3export GF180MCU_OSU_SC_COMMIT="8a2f58f283a2eaa725314c9e1b8b7d1d343f23a3"
4export GF180MCU_FD_PR_COMMIT="4adc3a4704fbe722bdf2145341a409b6419788fd"
5mkdir -p gf180mcu/spice
6mkdir -p gf180mcu/models
7curl -fsSL --retry 3 https://raw.githubusercontent.com/stineje/globalfoundries-pdk-libs-gf180mcu_osu_sc/$GF180MCU_OSU_SC_COMMIT/gf180mcu_osu_sc_gp9t3v3/spice/gf180mcu_osu_sc_gp9t3v3.spice > gf180mcu/spice/osu_sc_9t.spice
8curl -fsSL --retry 3 https://raw.githubusercontent.com/fossi-foundation/globalfoundries-pdk-libs-gf180mcu_fd_pr/$GF180MCU_FD_PR_COMMIT/models/ngspice/design.spice > gf180mcu/models/design.spice
9curl -fsSL --retry 3 https://raw.githubusercontent.com/fossi-foundation/globalfoundries-pdk-libs-gf180mcu_fd_pr/$GF180MCU_FD_PR_COMMIT/models/ngspice/sm141064.spice > gf180mcu/models/sm141064.spice

Example 1: OSU350 INVX1 Characterization

The example below is a configuration file for characterization of a single INVX1 inverter cell. When run with this configuration file, CharLib will measure the properties of the inverter and produce a liberty file called “osu350_inverter_example.lib”.

 1settings:
 2    lib_name: osu350_inverter_example
 3    units:
 4        # Specify all units for clarity, even though only resistance differs from the default
 5        time:               ns
 6        voltage:            V
 7        current:            uA
 8        pulling_resistance: kOhm
 9        leakage_power:      nW
10        capacitive_load:    pF
11        energy:             fJ
12    named_nodes:
13        primary_ground: # Tell CharLib the ground node name is different from the default "VSS"
14            name:   GND
15cells:
16    INVX1:
17        netlist:    osu350/spice/osu035_stdcells.sp
18        models:     [osu350/models/ami035.m]
19        area:       128
20        inputs:     [A]
21        outputs:    ['Y'] # Must be in quotes because YAML interprets Y as boolean True
22        functions:  [Y=!A]
23        data_slews: [0.015, 0.04, 0.08, 0.2, 0.4]
24        loads:      [0.06, 0.18, 0.42, 0.6, 1.2]

You can run this configuration by navigating to CharLib’s test/examples directory and executing the following commands.

./get_osu350.sh # Download OSU350 cell spice & transistor models
charlib run ex_osu350_invx1.yaml

Example 2: Characterizing Multiple OSU350 Combinational Cells

The YAML below configures CharLib to perform characterization of full adder (FAX1) and half adder (HAX1) cells. Notice the following changes from example 1:

  • Several cell parameters are moved into settings.cell_defaults to avoid repeating them for each cell.

  • The inputs and outputs keys are omitted from cell configurations. CharLib infers these from the cells’ functions instead.

 1settings:
 2    lib_name: osu350_adder_example
 3    units:
 4        pulling_resistance: kOhm # This is the only unit that differs from the defaults
 5    named_nodes:
 6        primary_ground:
 7            name: GND
 8    cell_defaults: # The key-value pairs below get copied to all cell configurations
 9        netlist:    osu350/spice/osu035_stdcells.sp
10        models:     [osu350/models/ami035.m]
11        data_slews: [0.015, 0.04, 0.08, 0.2, 0.4]
12        loads:      [0.06, 0.18, 0.42, 0.6, 1.2]
13cells:
14    FAX1:
15        area: 480
16        functions:
17            - YC=(A&B)|(C&(A^B))
18            - YS=A^B^C
19    HAX1:
20        area: 320
21        functions:
22            - YC=A&B
23            - YS=A^B
24        loads: [0.012, 0.036, 0.06] # This overrides the value from cell_defaults

You can run this configuration by navigating to CharLib’s test/examples directory and executing the following commands.

./get_osu350.sh # Download OSU350 cell spice & transistor models
charlib run ex_osu350_adders.yaml

Example 3: YAML-Free OSU350 DFFSR Characterization

CharLib may be used as a Python module without creating a separate YAML configuration file. The example below shows the characterization of an OSU350 sequential cell using this method. Note that this example will take quite a bit longer to run than the combinational examples above, as sequential cell characterization is much more complex than combinational.

Note

Using a CharLib Characterizer object directly (as shown below) bypasses all of the validation checks built into CharLib’s command-line interface. While this method of using CharLib can grant much finer control over the characterization process, we recommend the use of YAML configuration files to help avoid configuration errors.

 1from charlib.characterizer.characterizer import Characterizer
 2
 3if __name__ == "__main__":
 4    characterizer = Characterizer(
 5        lib_name='osu350_dffsr_example',
 6        units={'pulling_resistance': 'kOhm'},
 7        named_nodes={'primary_ground': {'name': 'GND'}})
 8    characterizer.add_cell('DFFSR', {
 9        'netlist':      'osu350/spice/osu035_stdcells.sp',
10        'models':       ['osu350/models/ami035.m'],
11        'area':         704,
12        'clock':        'posedge CLK',
13        'set':          'negedge S',
14        'reset':        'negedge R',
15        'state':        ['DS0000 = Q'],
16        'functions':    ['Q <= D'],
17        'data_slews':   [0.06, 0.18, 0.42, 0.6, 1.2],
18        'loads':        [0.015, 0.04, 0.08, 0.2, 0.4],
19        'clock_slews':  [0.06, 0.3, 0.6],
20        'metastability_constraint_search_tolerance': 0.01,
21        'metastability_constraint_search_timestep': 0.005,
22        'metastability_constraint_load': 0.24,
23        'metastability_constraint_sweep_samples': 40})
24    liberty = characterizer.characterize()
25    print(liberty)

Example 4: Characterizing Multiple gf180mcu Cells

The example below is a configuration file for characterization of several cells from the OSU 9-track standard cell library. This configuration includes a mix of combinational and sequential cells.

 1settings:
 2    lib_name: gf180mcu_osu_sc_9t_example
 3    cell_defaults:
 4        netlist: gf180mcu/spice/osu_sc_9t.spice
 5        models:
 6            - gf180mcu/models/sm141064.spice typical
 7            - gf180mcu/models/design.spice
 8        data_slews:  [0.0706, 0.1903, 0.5123, 1.3794, 3.7140]
 9        loads:       [0.0013, 0.0048, 0.0172, 0.0616, 0.2206, 0.7901]
10        clock_slews: [0.0699991, 2.64574]
11        metastability_constraint_load: 0.24
12cells:
13    gf180mcu_osu_sc_gp9t3v3__aoi21_1:
14        inputs: [A0, A1, B]
15        outputs: ['Y']
16        functions: [Y=(!A0&!B) | (!A1&!B)]
17    gf180mcu_osu_sc_gp9t3v3__aoi22_1:
18        inputs: [A0, A1, B0, B1]
19        outputs: ['Y']
20        functions: [Y=(!A0&!B0) | (!A0&!B1) | (!A1&!B0) | (!A1&!B1)]
21    gf180mcu_osu_sc_gp9t3v3__buf_1:
22        inputs: [A]
23        outputs: ['Y']
24        functions: [Y=A]
25    gf180mcu_osu_sc_gp9t3v3__dff_1:
26        functions:
27            - Q <= D
28            - QN <= !D
29        clock: posedge clk
30        state:
31            - IQ = Q
32            - IQN = QN
33        pairs: [Q QN]
34        # Limit DFFS to 1 slew/load/clk_slew corner, as this takes a long time
35        data_slews:  [0.0706]
36        loads:       [0.2206]
37        clock_slews: [0.0699991]
38    gf180mcu_osu_sc_gp9t3v3__mux2_1:
39        inputs: [A, B, SEL]
40        outputs: ['Y']
41        functions: [Y=(A&!SEL) | (B&SEL)]
42    gf180mcu_osu_sc_gp9t3v3__nand2_1:
43        inputs: [A, B]
44        outputs: ['Y']
45        functions: [Y=!(A&B)]
46    gf180mcu_osu_sc_gp9t3v3__nor2_1:
47        inputs: [A, B]
48        outputs: ['Y']
49        functions: [Y=!(A|B)]
50    gf180mcu_osu_sc_gp9t3v3__oai21_1:
51        inputs: [A0, A1, B]
52        outputs: ['Y']
53        functions: [Y=(!A0&!A1) | (!B)]
54    gf180mcu_osu_sc_gp9t3v3__oai22_1:
55        inputs: [A0, A1, B0, B1]
56        outputs: ['Y']
57        functions: [Y=(!A0&!A1) | (!B0&!B1)]
58    gf180mcu_osu_sc_gp9t3v3__oai31_1:
59        inputs: [A0, A1, A2, B]
60        outputs: ['Y']
61        functions: [Y=(!A0&!A1&!A2)|(!B)]
62    gf180mcu_osu_sc_gp9t3v3__or2_1:
63        inputs: [A, B]
64        outputs: ['Y']
65        functions: [Y=A|B]
66    gf180mcu_osu_sc_gp9t3v3__xnor2_1:
67        inputs: [A, B]
68        outputs: ['Y']
69        functions: [Y=!(A^B)]
70    gf180mcu_osu_sc_gp9t3v3__xor2_1:
71        inputs: [A, B]
72        outputs: ['Y']
73        functions: [Y=A^B]