Пример #1
0
def _add_cell(lib: Library, cell_info: Mapping[str, Any], pin_data: Mapping[str, Mapping[str, Any]]
              ) -> None:
    empty_list = []

    name: str = cell_info['name']
    props: Dict[str, Any] = cell_info['props']
    pwr_pins: Dict[str, str] = cell_info['pwr_pins']
    gnd_pins: Dict[str, str] = cell_info['gnd_pins']
    stdcell_pwr_pins: List[str] = cell_info.get('stdcell_pwr_pins', [])
    input_pins: List[Dict[str, Any]] = cell_info.get('input_pins', empty_list)
    output_pins: List[Dict[str, Any]] = cell_info.get('output_pins', empty_list)
    inout_pins: List[Dict[str, Any]] = cell_info.get('inout_pins', empty_list)

    cell = lib.create_cell(name, pwr_pins, gnd_pins, props, stdcell_pwr_pins=stdcell_pwr_pins)
    _add_pins(cell, TermType.input, input_pins, pin_data)
    _add_pins(cell, TermType.output, output_pins, pin_data)
    _add_pins(cell, TermType.inout, inout_pins, pin_data)
Пример #2
0
async def async_generate_liberty(prj: BagProject, lib_config: Mapping[str, Any],
                                 sim_config: Mapping[str, Any], cell_specs: Mapping[str, Any],
                                 fake: bool = False, extract: bool = False,
                                 force_sim: bool = False, force_extract: bool = False,
                                 gen_all_env: bool = False, gen_sch: bool = False,
                                 export_lay: bool = False, log_level: LogLevel = LogLevel.DEBUG
                                 ) -> None:
    """Generate liberty file for the given cells.

    Parameters
    ----------
    prj: BagProject
        BagProject object to be able to generate things
    lib_config : Mapping[str, Any]
        library configuration dictionary.
    sim_config : Mapping[str, Any]
        simulation configuration dictionary.
    cell_specs : Mapping[str, Any]
        cell specification dictionary.
    fake : bool
        True to generate fake liberty file.
    extract : bool
        True to run extraction.
    force_sim : bool
        True to force simulation runs.
    force_extract : bool
        True to force extraction runs.
    gen_all_env : bool
        True to generate liberty files for all environments.
    gen_sch : bool
        True to generate schematics.
    export_lay : bool
        Use CAD tool to export layout.
    log_level : LogLevel
        stdout logging level.
    """
    gen_specs_file: str = cell_specs['gen_specs_file']
    scenario: str = cell_specs.get('scenario', '')

    gen_specs: Mapping[str, Any] = read_yaml(gen_specs_file)
    impl_lib: str = gen_specs['impl_lib']
    impl_cell: str = gen_specs['impl_cell']
    lay_cls: str = gen_specs['lay_class']
    dut_params: Mapping[str, Any] = gen_specs['params']
    name_prefix: str = gen_specs.get('name_prefix', '')
    name_suffix: str = gen_specs.get('name_suffix', '')
    gen_root_dir: Path = Path(gen_specs['root_dir'])
    lib_root_dir = gen_root_dir / 'lib_gen'

    sim_precision: int = sim_config['precision']

    dsn_options = dict(
        extract=extract,
        force_extract=force_extract,
        gen_sch=gen_sch,
        log_level=log_level,
    )
    log_file = str(lib_root_dir / 'lib_gen.log')
    sim_db = prj.make_sim_db(lib_root_dir / 'dsn', log_file, impl_lib, dsn_options=dsn_options,
                             force_sim=force_sim, precision=sim_precision, log_level=log_level)
    dut = await sim_db.async_new_design(impl_cell, lay_cls, dut_params, export_lay=export_lay,
                                        name_prefix=name_prefix, name_suffix=name_suffix)

    environments: Mapping[str, Any] = lib_config['environments']
    nom_voltage_type: str = environments['nom_voltage_type']
    name_format: str = environments['name_format']
    voltage_precision: int = environments['voltage_precision']
    sim_env_list: List[Mapping[str, Any]] = environments['sim_envs']
    if not gen_all_env:
        sim_env_list = [sim_env_list[0]]

    voltage_fmt = '{:.%df}' % voltage_precision
    lib_file_base_name = f'{impl_cell}_{scenario}' if scenario else impl_cell
    for sim_env_config in sim_env_list:
        sim_env: str = sim_env_config['sim_env']
        voltages: Mapping[str, float] = sim_env_config['voltages']

        vstr_table = {k: voltage_fmt.format(v).replace('.', 'p') for k, v in voltages.items()}
        sim_env_name = name_format.format(sim_env=sim_env, **vstr_table)
        lib_file_name = f'{lib_file_base_name}_{sim_env_name}'

        cur_lib_config = dict(**lib_config)
        cur_lib_config.pop('environments')

        # setup lib config
        temperature = get_corner_temp(sim_env)[1]
        env_config = dict(
            name=sim_env_name,
            bag_name=sim_env,
            process=1.0,
            temperature=temperature,
            voltage=voltages[nom_voltage_type],
        )

        cur_lib_config['voltages'] = voltages
        cur_lib_config['sim_envs'] = [env_config]
        lib = Library(f'{impl_cell}_{sim_env_name}', cur_lib_config)

        out_file = gen_root_dir / f'{lib_file_name}.lib'
        lib_data, mm_specs, cur_work_dir = get_cell_info(lib, impl_cell, cell_specs,
                                                         lib_root_dir, voltage_fmt)

        mm_specs['fake'] = fake
        mm_specs['sim_env_name'] = sim_env_name
        for key in ['tran_tbm_specs', 'buf_params', 'in_cap_search_params', 'out_cap_search_params',
                    'seq_search_params', 'seq_delay_thres']:
            mm_specs[key] = sim_config[key]
        mm = sim_db.make_mm(LibertyCharMM, mm_specs)

        sim_db.log(f'Characterizing {lib_file_name}.lib')
        char_results = await sim_db.async_simulate_mm_obj('lib_char', cur_work_dir, dut, mm)
        pin_data = char_results.data

        _add_cell(lib, lib_data, pin_data)
        lib.generate(out_file)
Пример #3
0
def get_cell_info(lib: Library, impl_cell: str, cell_specs: Mapping[str, Any], lib_root_dir: Path,
                  voltage_fmt: str) -> Tuple[Mapping[str, Any], Dict[str, Any], Path]:
    sim_envs = lib.sim_envs
    if len(sim_envs) != 1:
        raise ValueError('Only support one corner per liberty file.')

    in_cap_range_scale: float = cell_specs['input_cap_range_scale']
    in_cap_min: float = cell_specs.get('input_cap_min', 1.0e-15)
    in_cap_guess: float = cell_specs.get('input_cap_guess', in_cap_min)
    out_min_fanout: float = cell_specs.get('min_fanout', 0.5)

    stdcell_pwr_pins: Sequence[str] = cell_specs.get('stdcell_pwr_pins', [])
    input_pins: Sequence[Mapping[str, Any]] = cell_specs.get('input_pins', [])
    output_pins: Sequence[Mapping[str, Any]] = cell_specs.get('output_pins', [])
    inout_pins: Sequence[Mapping[str, Any]] = cell_specs.get('inout_pins', [])
    pwr_pins: Mapping[str, str] = cell_specs['pwr_pins']
    gnd_pins: Mapping[str, str] = cell_specs['gnd_pins']

    in_defaults: Mapping[str, Any] = cell_specs.get('input_pins_defaults', {})
    out_defaults: Mapping[str, Any] = cell_specs.get('output_pins_defaults', {})
    inout_defaults: Mapping[str, Any] = cell_specs.get('inout_pins_defaults', {})

    pin_values: Mapping[str, int] = cell_specs.get('cond_defaults', {})

    seq_timing: Mapping[str, Any] = cell_specs.get('seq_timing', {})

    cell_props: Mapping[str, Any] = cell_specs.get('props', {})
    diff_list: Sequence[Tuple[Sequence[str], Sequence[str]]] = cell_props.get('pin_opposite', [])

    custom_meas: Mapping[str, Mapping[str, Any]] = cell_specs.get('custom_measurements', {})

    # get supply values
    sup_values: Dict[str, float] = {}
    for pin, vtype in chain(pwr_pins.items(), gnd_pins.items()):
        sup_values[pin] = lib.get_voltage(vtype)

    # gather pin information
    pwr_domain: Dict[str, Tuple[str, str]] = {}
    reset_table: Dict[str, bool] = {}
    in_cap_table: Dict[str, float] = {}
    in_pin_list = _get_pin_info_list(input_pins, in_defaults, pwr_domain, reset_table,
                                     in_cap_table, in_cap_guess)
    io_pin_list = _get_pin_info_list(inout_pins, inout_defaults, pwr_domain)
    out_pin_list = _get_pin_info_list(output_pins, out_defaults, pwr_domain)

    lut_delay = lib.get_lut(LUTType.DELAY)
    delay_shape = lut_delay.shape
    delay_swp_info = lut_delay.get_swp_info(dict(trf_src='t_rf', cload='c_load'))
    seq_swp_info = lut_delay.get_swp_info(dict(trf_src='t_clk_rf', cload='c_load'))

    lut_cons = lib.get_lut(LUTType.CONSTRAINT)
    t_rf_list = lut_cons['trf_in']
    t_clk_rf_list = lut_cons['trf_src']
    cons_swp_order = lut_cons.get_swp_order(dict(trf_src='t_clk_rf', trf_in='t_rf'))

    out_io_info_table = dict(chain(_pin_info_iter(out_pin_list), _pin_info_iter(io_pin_list)))
    out_cap_num_freq = len(lib.get_lut(LUTType.MAX_CAP)['freq'])
    mm_specs = dict(
        sim_envs=sim_envs,
        thres_lo=lib.thres_lo,
        thres_hi=lib.thres_hi,
        in_cap_min_default=in_cap_min,
        in_cap_range_scale=in_cap_range_scale,
        out_max_trf=lib.get_max_input_transition(LogicType.COMB, is_clock=False),
        out_min_fanout=out_min_fanout,
        out_cap_num_freq=out_cap_num_freq,
        in_cap_table=in_cap_table,
        out_io_info_table=out_io_info_table,
        seq_timing=seq_timing,
        custom_meas=custom_meas,

        delay_shape=delay_shape,
        delay_swp_info=delay_swp_info,
        seq_shape=delay_shape,
        seq_swp_info=seq_swp_info,
        t_rf_list=t_rf_list,
        t_clk_rf_list=t_clk_rf_list,
        t_clk_rf_first=(cons_swp_order[0] == 't_clk_rf'),

        dut_info=dict(
            pwr_domain=pwr_domain,
            sup_values=sup_values,
            pin_values=pin_values,
            reset_list=list(reset_table.items()),
            diff_list=diff_list,
        ),
    )

    # get working directory
    vstr_table = {k: voltage_fmt.format(v).replace('.', 'p') for k, v in sup_values.items()}
    voltage_string = '_'.join((f'{k}_{vstr_table[k]}' for k in sorted(vstr_table.keys())))
    work_dir = lib_root_dir / sim_envs[0] / voltage_string

    # construct result dictionary
    lib_data = {k: cell_specs[k] for k in ['props', 'pwr_pins', 'gnd_pins']}
    lib_data['name'] = impl_cell
    lib_data['stdcell_pwr_pins'] = stdcell_pwr_pins
    lib_data['input_pins'] = in_pin_list
    lib_data['output_pins'] = out_pin_list
    lib_data['inout_pins'] = io_pin_list
    return lib_data, mm_specs, work_dir