Source code for bag3_testbenches.measurement.digital.max_trf

# 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, Sequence, Mapping, Dict, Set, 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
from ..tran.digital import DigitalTranTB
from .util import setup_digital_tran


[docs]class MaxRiseFallTime(IntervalSearchMM): """Tweaks a parameter as far as possible without exceeding max rise/fall time. Notes ----- specification dictionary has the following entries: adj_name : str the adjust parameter name. in_pin : str input pin name. out_pin : str output pin name. adj_sign : bool True if increasing parameter value increases rise/fall time, False otherwise. max_trf : float maximum rise/fall time, in seconds. 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_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. 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)
[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 out_pin: str = specs['out_pin'] adj_name: str = specs['adj_name'] adj_sign: bool = specs['adj_sign'] max_trf: float = specs['max_trf'] cur_state = cur_info.state data = sim_results.data tbm = cast(DigitalTranTB, sim_results.tbm) t0 = tbm.get_t_rst_end(data) tr = tbm.calc_trf(data, out_pin, True, allow_inf=True, t_start=t0) tf = tbm.calc_trf(data, out_pin, False, allow_inf=True, t_start=t0) adj_values = data[adj_name] # remove corners tr = tr[0, ...] tf = tf[0, ...] # replace NaN with inf to force to use smaller values tr[np.isnan(tr)] = np.inf tf[np.isnan(tf)] = np.inf # find sign change trf_max = np.maximum(tr, tf) diff = max_trf - trf_max res_idx, accept, low, high = self.get_adj_interval(adj_name, not adj_sign, adj_values, diff) new_result = {'value': adj_values[res_idx], 'tr': tr[res_idx], 'tf': tf[res_idx]} self.log_result(cur_state, new_result) return {adj_name: ((low, high), new_result, accept)}