Source code for bag3_testbenches.measurement.digital.delay_match

# SPDX-License-Identifier: Apache-2.0
# 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.

from __future__ import annotations

from typing import Any, Tuple, Mapping, Dict, Set, Optional, Sequence, cast

import numpy as np

from bag.simulation.core import TestbenchManager
from bag.simulation.cache import SimulationDB, DesignInstance, SimResults
from bag.simulation.measure import MeasInfo

from ..search import IntervalSearchMM, AcceptMode
from ..tran.digital import DigitalTranTB
from .util import setup_digital_tran


[docs]class DelayMatch(IntervalSearchMM): """This class tweaks a given parameter to match two delays. This class adjusts a given parameter using binary search to try and match the delay of two different paths, or the delay of a single path to a target number. Most often this is used to extract input capacitance. Assumptions: 1. There are no corner or parameter sweeps. 2. the reference and adjust delay paths have the same out_invert value. Notes ----- specification dictionary has the following entries: adj_name : str the adjust parameter name. adj_sign : bool True if increasing parameter value increases delay, False otherwise. adj_params : Mapping[str, Any] adjust delay path parameters. ref_delay : float Optional. The target delay value. ref_params : Mapping[str, Any] reference delay path parameters. Used only if ref_delay is not present. use_dut : bool Optional. True to instantiate DUT. Defaults to True. search_params : Mapping[str, Any] interval search parameters, with the following entries: low : float lower bound. high : Optional[float] upper bound. If None, perform a unbounded binary search. step : float initial step size for unbounded binary search. tol : float tolerance of the binary search. Terminate the search when it is below this value. max_err : float Used only in unbounded binary search. If unbounded binary search exceeds this value, raise an error. overhead_factor : float ratio of simulation startup time to time it takes to simulate one sweep point. tbm_specs : Mapping[str, Any] DigitalTranTB related specifications. The following simulation parameters are required: t_sim : total simulation time. t_rst : reset duration. t_rst_rf : reset rise/fall time. t_bit : bit value duration. t_rf : input pulse rise/fall time. wrapper_params : Mapping[str, Any] Used only if simulated with a DUT wrapper. Contains the following entries: lib : str wrapper library name. cell : str wrapper cell name. params : Mapping[str, Any] DUT wrapper schematic parameters. pins : Sequence[str] wrapper pin list. power_domain : Mapping[str, Tuple[str, str] power domain of wrapper. pulse_list : Sequence[Mapping[str, Any]] List of pulse sources. Each dictionary has the following entries: pin : str the pin to connect to. tper : Union[float, str] period. tpw : Union[float, str] the flat region duration. trf : Union[float, str] rise/fall time. td : Union[float, str] Optional. Pulse delay in addition to any reset period. Defaults to 0. pos : bool Optional. True if this is a positive pulse (010). Defaults to True. load_list : Sequence[Mapping[str, Any]] Optional. List of loads. Each dictionary has the following entries: pin: str the pin to connect to. type : str the load device type. value : Union[float, str] the load parameter value. """ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._value: Optional[float] = None
[docs] def process_init(self, cur_info: MeasInfo, sim_results: SimResults ) -> Tuple[Dict[str, Any], bool]: return {}, False
[docs] def process_output_helper(self, cur_info: MeasInfo, sim_results: SimResults, remaining: Set[str]) -> Mapping[str, Tuple[Tuple[float, float], Dict[str, Any], bool]]: specs = self.specs adj_name: str = specs['adj_name'] adj_sign: bool = specs['adj_sign'] adj_params: Mapping[str, Any] = specs['adj_params'] cur_state = cur_info.state data = sim_results.data tbm = cast(DigitalTranTB, sim_results.tbm) td_adj = tbm.calc_delay(data, **adj_params) adj_values = data[adj_name] # remove corners td_adj = td_adj[0, ...] if self._value is None: ref_params: Mapping[str, Any] = specs['ref_params'] td_ref = tbm.calc_delay(data, **ref_params) td_ref = td_ref[0, ...] else: td_ref = np.full(td_adj.shape, self._value) # find sign change diff = td_ref - td_adj arg, accept, low, high = self.get_adj_interval(adj_name, not adj_sign, adj_values, diff, accept_mode=AcceptMode.BOTH) new_result = {'value': adj_values[arg].item(), 'td_ref': td_ref[arg].item(), 'td_adj': td_adj[arg].item(), 'accept': accept} self.log_result(cur_state, new_result) return {adj_name: ((low, high), new_result, accept)}