Source code for bag.verification.pvs

# SPDX-License-Identifier: BSD-3-Clause AND Apache-2.0
# Copyright 2018 Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Copyright 2019 Blue Cheetah Analog Design Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This module implements LVS/RCX using PVS/QRC and stream out from Virtuoso.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Optional, List, Dict, Any, Sequence, Tuple, Union

from pathlib import Path

from ..io import read_file, write_file
from ..io.file import is_valid_file

from .virtuoso import VirtuosoChecker

if TYPE_CHECKING:
    from .base import FlowInfo


[docs]class PVS(VirtuosoChecker): """A subclass of VirtuosoChecker that uses PVS/QRC for verification. Parameters ---------- tmp_dir : str temporary directory to save files in. root_dir : Dict[str, str] dictionary of root run directories. template : Dict[str, str] dictionary of SVRF jinja template files. env_vars: Dict[str, Dict[str, str]] dictionary of environment variables. params : Dict[str, Dict[str, Any]] dictionary of default flow parameters. lvs_cmd : str the lvs command. max_workers : int maximum number of sub-processes BAG can launch. source_added_file : str the Calibre source.added file location. Environment variable is supported. If empty (default), this is not configured. import_ref_lib : str the import reference libraries list file location. Environment variable is supported. If empty (default), this is not configured. cancel_timeout_ms : int cancel timeout in milliseconds. enable_color : bool True to enable coloring in GDS export. """ def __init__(self, tmp_dir: str, root_dir: Dict[str, str], template: Dict[str, str], env_vars: Dict[str, Dict[str, str]], link_files: Dict[str, List[str]], params: Dict[str, Dict[str, Any]], lvs_cmd: str = 'pvs', max_workers: int = 0, source_added_file: str = '', import_ref_lib: str = '', cancel_timeout_ms: int = 10000, enable_color: bool = False, **kwargs: Dict[str, Any]) -> None: VirtuosoChecker.__init__(self, tmp_dir, root_dir, template, env_vars, link_files, params, max_workers, source_added_file, import_ref_lib, cancel_timeout_ms, enable_color, **kwargs) self._lvs_cmd = lvs_cmd
[docs] def get_rcx_netlists(self, lib_name: str, cell_name: str) -> List[str]: # PVS generate schematic cellviews directly. return [f'{cell_name}.spf']
[docs] def setup_drc_flow(self, lib_name: str, cell_name: str, lay_view: str = 'layout', layout: str = '', params: Optional[Dict[str, Any]] = None, run_dir: Union[str, Path] = '') -> Sequence[FlowInfo]: raise NotImplementedError('Not supported yet.')
[docs] def setup_lvs_flow(self, lib_name: str, cell_name: str, sch_view: str = 'schematic', lay_view: str = 'layout', layout: str = '', netlist: str = '', params: Optional[Dict[str, Any]] = None, run_rcx: bool = False, run_dir: Union[str, Path] = '') -> Sequence[FlowInfo]: mode = 'lvs_rcx' if run_rcx else 'lvs' tmp = self.setup_job(mode, lib_name, cell_name, layout, netlist, lay_view, sch_view, params, run_dir) flow_list, run_dir_path, run_env, params, ctl_params = tmp if ctl_params['layout_type'] != 'GDSII': raise ValueError('Only LVS with gds file is supported.') # generate new control file ctl_path = run_dir_path / f'bag_{mode}.ctrl' temp = self.get_control_template(mode) content = temp.render(**ctl_params) write_file(ctl_path, content) cmd = [self._lvs_cmd, '-perc', '-lvs', '-control', str(ctl_path), '-gds', ctl_params['layout_file'], '-layout_top_cell', cell_name, '-source_cdl', ctl_params['netlist_file'], '-source_top_cell', cell_name, 'pvs_rules'] if run_rcx: cmd.insert(3, '-qrc_data') log_path = run_dir_path / f'bag_{mode}.log' flow_list.append((cmd, str(log_path), run_env, str(run_dir_path), _lvs_passed_check)) return flow_list
[docs] def setup_rcx_flow(self, lib_name: str, cell_name: str, sch_view: str = 'schematic', lay_view: str = 'layout', layout: str = '', netlist: str = '', params: Optional[Dict[str, Any]] = None, run_dir: Union[str, Path] = '' ) -> Sequence[FlowInfo]: # noinspection PyUnusedLocal def _rcx_passed_check(retcode: int, log_file: str) -> Tuple[str, str]: out_file = Path(log_file).parent.resolve() out_file = out_file.joinpath(f'{cell_name}.spf') if not is_valid_file(out_file, None, 60, 1): return '', log_file return str(out_file), log_file mode = 'rcx' tmp = self.setup_job(mode, lib_name, cell_name, layout, netlist, lay_view, sch_view, params, run_dir) flow_list, run_dir, run_env, params, ctl_params = tmp ctl_path = run_dir / f'bag_{mode}.ctrl' ctl_template = self.get_control_template(mode) content = ctl_template.render(**ctl_params) write_file(ctl_path, content) # generate new control file run_cmd = ['qrc', '-64', '-cmd', str(ctl_path)] log_path = run_dir / f'bag_{mode}.log' flow_list.append((run_cmd, str(log_path), run_env, str(run_dir), _rcx_passed_check)) return flow_list
# noinspection PyUnusedLocal
[docs]def _lvs_passed_check(retcode: int, log_file: str) -> Tuple[bool, str]: """Check if LVS passed Parameters ---------- retcode : int return code of the LVS subprocess. log_file : str log file name. Returns ------- success : bool True if LVS passed. log_file : str the log file name. """ fpath = Path(log_file) if not is_valid_file(fpath, 'PVS Comparison Finished.', 60, 1): return False, log_file if fpath.is_file() else '' cmd_output = read_file(fpath) test_str = '# Run Result : MATCH' return test_str in cmd_output, log_file