Beispiel #1
0
def plot_gain_bw(specs, sim_params, fg_load_list, env):
    vname = 'outac'
    base_name = specs['impl_cell']
    save_root = sim_params['save_root']
    vload_list = sim_params['vload_list']
    gain_mat = np.empty((len(fg_load_list), len(vload_list)))
    bw_mat = np.empty((len(fg_load_list), len(vload_list)))
    for fg_idx, fg_load in enumerate(fg_load_list):
        fname = os.path.join(save_root, '%s_fg%d.hdf5' % (base_name, fg_load))
        results = load_sim_file(fname)

        swp_pars = results['sweep_params'][vname]
        corners = results['corner']
        corner_idx = swp_pars.index('corner')
        env_idx = np.argwhere(corners == env)[0][0]
        data = np.take(results[vname], env_idx, axis=corner_idx)
        vload_idx = swp_pars.index('vload')
        vload_vec = results['vload']
        for idx in range(vload_vec.size):
            outac = np.take(data, idx, axis=vload_idx)
            gain, f3db = compute_gain_and_w3db(results['freq'], outac)
            gain_mat[fg_idx, idx] = gain
            bw_mat[fg_idx, idx] = f3db

    plot_mat(1, '$A_v$ (V/V)', gain_mat, fg_load_list, vload_list)
    plot_mat(2, '$f_{3db}$ (Hz)', bw_mat, fg_load_list, vload_list)
    plt.show()
Beispiel #2
0
    def process_output(
            self,
            state,  # type: str
            data,  # type: Dict[str, Any]
            tb_manager,  # type: Union[MOSIdTB, MOSSPTB, MOSNoiseTB]
    ):
        # type: (...) -> Tuple[bool, str, Dict[str, Any]]

        ss_fname = os.path.join(self.data_dir, 'ss_params.hdf5')
        if state == 'ibias':
            done = False
            next_state = 'sp'
            vgs_range = tb_manager.get_vgs_range(data)
            output = dict(vgs_range=vgs_range)
        elif state == 'sp':
            testbenches = self.specs['testbenches']
            if 'noise' in testbenches:
                done = False
                next_state = 'noise'
            else:
                done = True
                next_state = ''

            ss_params = tb_manager.get_ss_params(data)
            # save SS parameters
            save_sim_results(ss_params, ss_fname)
            output = dict(ss_file=ss_fname)
        elif state == 'noise':
            done = True
            next_state = ''

            temp = self.specs['noise_temp_kelvin']
            fstart = self.specs['noise_integ_fstart']
            fstop = self.specs['noise_integ_fstop']
            scale = self.specs.get('noise_integ_scale', 1.0)

            ss_params = load_sim_file(ss_fname)
            ss_params = tb_manager.get_integrated_noise(data,
                                                        ss_params,
                                                        temp,
                                                        fstart,
                                                        fstop,
                                                        scale=scale)
            save_sim_results(ss_params, ss_fname)

            output = dict(ss_file=ss_fname)
        else:
            raise ValueError('Unknown state: %s' % state)

        return done, next_state, output
def simulate(prj, specs_fname):
    # simulate and report result
    sim = DesignManager(prj, specs_fname)
    sim.characterize_designs(generate=True, measure=True, load_from_file=False)
    # sim.test_layout(gen_sch=False)

    dsn_name = list(sim.get_dsn_name_iter())[0]
    summary = sim.get_result(dsn_name)
    fname = summary['ac']['gain_w3db_file']
    result = load_sim_file(fname)
    gain = result['gain_vout']
    w3db = result['w3db_vout']
    print('%s gain = %.4g' % (dsn_name, gain))
    print('%s w3db = %.4g' % (dsn_name, w3db))

    return gain, w3db
Beispiel #4
0
def run_main(prj):
    # save_fname = 'blocks_ec_tsmcN16/data/gm_char_dc/linearity_stack.hdf5'
    save_fname = 'blocks_ec_tsmcN16/data/gm_char_dc/linearity_stack.hdf5'

    sim_env = 'tt'
    vdd = 0.9
    voutcm = 0.7
    tper = 70e-12
    ck_amp = 0.3
    ck_bias = 0.05
    rel_err = 0.05
    cload = 5e-15
    bias_vec = np.linspace(0, 0.15, 16, endpoint=True)
    dc_params = dict(
        num_k=7,
        sim_env=sim_env,
        method='linear',
    )
    vstar_params = dict(
        tol=1e-3,
        num=21,
        method='cubic',
    )

    sim_params = dict(
        dut_lib='CHAR_INTEG_AMP_STACK_TSW',
        impl_lib='CHAR_INTEG_AMP_STACK_TSW_TB',
        impl_cell='gm_char_dc',
        save_fname=save_fname,
        tb_lib='bag_serdes_testbenches_ec',
        tb_cell='gm_char_dc',
        dut_cell='INTEG_AMP',
        env_list=['tt', 'ff_hot', 'ss_cold'],
        sim_view='av_extracted',
    )

    # simulate(prj, **sim_params)

    result = load_sim_file(save_fname)
    # plot_data_2d(result, 'ioutp', sim_env='tt')
    # get_transient(result, 15, tper, ck_amp, ck_bias, **kwargs)
    # get_dc_tf(result, tper, ck_amp, ck_bias, plot=True, **dc_params)
    plot_vstar(result, tper, vdd, cload, bias_vec, ck_amp, rel_err, dc_params,
               vstar_params)
Beispiel #5
0
    def __init__(self,
                 prj: BagProject,
                 spec_list: List[str],
                 interp_method: str = 'spline',
                 vgs_res: float = 5e-3,
                 width_var: str = 'w') -> None:

        self._width_res = prj.tech_info.tech_params['mos']['width_resolution']
        self._sim_envs = None
        self._ss_swp_names = None
        self._dsn_info_list: List[MOSCharSpecs] = []
        self._ss_list = []
        self._ss_outputs = None
        self._width_list = []
        self._vgs_res = vgs_res

        for spec in spec_list:
            dsn_info = MOSCharSpecs(spec)
            cur_width = dsn_info.specs['dut_params'][width_var]
            cur_width = int(round(cur_width / self._width_res))
            self._width_list.append(cur_width)

            # error checking
            if 'w' in dsn_info.swp_var_list:
                raise ValueError(
                    'MOSDBDiscrete assumes transistor width is not swept.')

            ss_fun_table = {}
            for dsn_name in dsn_info.dsn_name_iter():
                meas_dir = dsn_info.root_dir / dsn_info.specs[
                    'meas_name']  # FIXME
                ss_dict = load_sim_file(
                    os.path.join(str(meas_dir), 'ss_params.hdf5'))

                cur_corners = ss_dict['corner'].tolist()
                cur_ss_swp_names = ss_dict['sweep_params']['ibias'][1:]
                if self._sim_envs is None:
                    # assign attributes for the first time
                    self._sim_envs = cur_corners
                    self._ss_swp_names = cur_ss_swp_names
                elif self._sim_envs != cur_corners:
                    raise ValueError(
                        'Simulation environments mismatch between given specs.'
                    )
                elif self._ss_swp_names != cur_ss_swp_names:
                    raise ValueError(
                        'signal-signal parameter sweep names mismatch.')

                cur_fun_dict = self._make_ss_functions(ss_dict, cur_corners,
                                                       cur_ss_swp_names,
                                                       interp_method)

                if self._ss_outputs is None:
                    self._ss_outputs = sorted(cur_fun_dict.keys())

                ss_fun_table[dsn_name] = cur_fun_dict

            self._dsn_info_list.append(dsn_info)
            self._ss_list.append(ss_fun_table)

        self._env_list = self._sim_envs
        self._cur_idx = 0
        self._dsn_params = dict(w=self._width_list[0] * self._width_res)
Beispiel #6
0
    def __init__(
        self,
        spec_list,  # type: List[str]
        interp_method='spline',  # type: str
        bag_config_path=None,  # type: Optional[str]
        meas_type='mos_ss',  # type: str
        vgs_res=5e-3,  # type: float
        is_schematic=False,
        width_var='w',
    ):
        # type: (...) -> None
        # error checking

        tech_info = create_tech_info(bag_config_path=bag_config_path)

        self._width_res = tech_info.tech_params['mos']['width_resolution']
        self._sim_envs = None
        self._ss_swp_names = None
        self._manager_list = []  # type: List[DesignManager]
        self._ss_list = []
        self._ss_outputs = None
        self._width_list = []
        self._vgs_res = vgs_res

        param_name = 'schematic_params' if is_schematic else 'layout_params'
        for spec in spec_list:
            dsn_manager = DesignManager(None, spec)
            cur_width = dsn_manager.specs[param_name][width_var]
            cur_width = int(round(cur_width / self._width_res))
            self._width_list.append(cur_width)

            # error checking
            if 'w' in dsn_manager.swp_var_list:
                raise ValueError(
                    'MOSDBDiscrete assumes transistor width is not swept.')

            ss_fun_table = {}
            for dsn_name in dsn_manager.get_dsn_name_iter():
                meas_dir = dsn_manager.get_measurement_directory(
                    dsn_name, meas_type)
                ss_dict = load_sim_file(
                    os.path.join(meas_dir, 'ss_params.hdf5'))

                cur_corners = ss_dict['corner'].tolist()
                cur_ss_swp_names = ss_dict['sweep_params']['ibias'][1:]
                if self._sim_envs is None:
                    # assign attributes for the first time
                    self._sim_envs = cur_corners
                    self._ss_swp_names = cur_ss_swp_names
                elif self._sim_envs != cur_corners:
                    raise ValueError(
                        'Simulation environments mismatch between given specs.'
                    )
                elif self._ss_swp_names != cur_ss_swp_names:
                    raise ValueError(
                        'signal-signal parameter sweep names mismatch.')

                cur_fun_dict = self._make_ss_functions(ss_dict, cur_corners,
                                                       cur_ss_swp_names,
                                                       interp_method)

                if self._ss_outputs is None:
                    self._ss_outputs = sorted(cur_fun_dict.keys())

                ss_fun_table[dsn_name] = cur_fun_dict

            self._manager_list.append(dsn_manager)
            self._ss_list.append(ss_fun_table)

        self._env_list = self._sim_envs
        self._cur_idx = 0
        self._dsn_params = dict(w=self._width_list[0] * self._width_res)
Beispiel #7
0
    async def async_measure_performance(self, name: str, sim_dir: Path, sim_db: SimulationDB,
                                        dut: Optional[DesignInstance]) -> Dict[str, Any]:
        """
        A coroutine that performs measurement.
        This will...
        1. Acquire every sweep point/configuration (get_swp_list)
        2. Run simulation for each sweep point (_run_sim)
        3. Aggregate results and return (aggregate_results)

        Parameters
        ----------
        name : str
            name of measurement
        sim_dir : Path
            simulation directory
        sim_db : SimulationDB
            the simulation database object
        dut : Optional[DesignInstance]
            the DUT to measure

        Returns
        -------
        results dictionary

        """
        assert len(self._sim_envs) > 0
        self.tbm_dict: Dict[str, TestbenchManager] = {k: None for k in self.tbm_order}

        res = {}

        for idx, tbm_name in enumerate(self.tbm_order):
            if not self._run_tbm[tbm_name]:
                continue

            tbm = self.add_tbm(tbm_name)
            sim_results = await sim_db.async_simulate_tbm_obj(tbm_name, sim_dir / tbm_name, dut, tbm, tb_params={})
            data = sim_results.data

            ss_fname = str(sim_dir / 'ss_params.hdf5')

            if tbm_name == 'ibias':
                tbm: MOSIdTB
                vgs_range = tbm.get_vgs_range(data)
                if self._run_tbm['sp']:
                    self.specs['tbm_specs']['sp']['vgs_range'] = vgs_range
                if self._run_tbm['noise']:
                    self.specs['tbm_specs']['noise']['vgs_range'] = vgs_range
                self.commit()
                res['vgs_range'] = vgs_range

            elif tbm_name == 'sp':
                tbm: MOSSPTB
                ss_params = tbm.get_ss_params(data)
                # save SS parameters
                save_sim_results(ss_params, ss_fname)

                res['ss_file'] = ss_fname

            elif tbm_name == 'noise':
                # TODO: needs to be verified
                tbm: MOSNoiseTB
                temp = self.specs['noise_temp_kelvin']
                fstart = self.specs['noise_integ_fstart']
                fstop = self.specs['noise_integ_fstop']
                scale = self.specs.get('noise_integ_scale', 1.0)

                ss_params = load_sim_file(ss_fname)
                ss_params = tbm.get_integrated_noise(data, ss_params, temp, fstart, fstop, scale=scale)
                save_sim_results(ss_params, ss_fname)

                res['ss_file'] = ss_fname

            else:
                raise ValueError(f"Unknown tbm name {tbm_name}")

        write_yaml(sim_dir / f'{name}.yaml', res)

        return res