def get_layout_basename(self): """Returns the base name for this template. Returns ------- base_name : str the base name of this template. """ lch_str = float_to_si_string(self.params['lch']) w_str = float_to_si_string(self.params['w']) prefix = 'mconn' if self.params['is_diff']: prefix += '_diff' basename = '%s_l%s_w%s_fg%d_s%d_d%d_g%s' % ( prefix, lch_str, w_str, self.params['fg'], self.params['sdir'], self.params['ddir'], self.params['gate_pref_loc'], ) if self.params['min_ds_cap']: basename += '_minds' if self.params['diode_conn']: basename += '_diode' gext = self.params['gate_ext_mode'] if gext > 0: basename += '_gext%d' % gext return basename
def get_layout_basename(self): # type: () -> str lch_str = float_to_si_string(self.params['lch']) w_str = float_to_si_string(self.params['w']) prefix = 'mconn' if self.params['is_diff']: prefix += '_diff' basename = '%s_l%s_w%s_fg%d_s%d_d%d_g%s' % ( prefix, lch_str, w_str, self.params['fg'], self.params['sdir'], self.params['ddir'], self.params['gate_pref_loc'], ) if self.params['min_ds_cap']: basename += '_minds' if self.params['diode_conn']: basename += '_diode' gext = self.params['gate_ext_mode'] if gext > 0: basename += '_gext%d' % gext return basename
def design(self, dut_lib, dut_cell, gain_cmfb, cload, cfb, rfb, vdd): """Create the OpAmp wrapper for simulation purposes. """ if not dut_lib or not dut_cell: raise ValueError('Invalid dut_lib/dut_cell = (%s, %s)' % (dut_lib, dut_cell)) self.replace_instance_master('XDUT', dut_lib, dut_cell, static=True) vcvs = self.instances['ECMFB'] if not isinstance(gain_cmfb, str): gain_cmfb = float_to_si_string(gain_cmfb) if not isinstance(vdd, str): vdd = float_to_si_string(vdd) if not isinstance(cload, str): cload = float_to_si_string(cload) if not isinstance(cfb, str): cfb = float_to_si_string(cfb) if not isinstance(rfb, str): rfb = float_to_si_string(rfb) vcvs.parameters['egain'] = gain_cmfb vcvs.parameters['minm'] = '0.0' vcvs.parameters['maxm'] = vdd self.instances['COUTP'].parameters['c'] = cload self.instances['COUTN'].parameters['c'] = cload self.instances['CFBP'].parameters['c'] = cfb self.instances['CFBN'].parameters['c'] = cfb self.instances['RFBP'].parameters['r'] = rfb self.instances['RFBN'].parameters['r'] = rfb
def get_layout_basename(self): fmt = '%s_l%s_w%s_%s' mos_type = self.params['mos_type'] lstr = float_to_si_string(self.params['lch']) wstr = float_to_si_string(self.params['w']) th = self.params['threshold'] return fmt % (mos_type, lstr, wstr, th)
def get_schematic_parameters(self): # type: () -> Dict[str, str] w = self.params['w'] l = self.params['l'] wstr = w if isinstance(w, str) else float_to_si_string(w) lstr = l if isinstance(l, str) else float_to_si_string(l) return dict(w=wstr, l=lstr)
def get_layout_basename(self): fmt = 'ext_l%s_w%s_fg%d' lstr = float_to_si_string(self.params['lch']) wstr = float_to_si_string(self.params['w']) fg = self.params['fg'] ans = fmt % (lstr, wstr, fg) if self.params['is_laygo']: ans = 'laygo_' + ans return ans
def get_schematic_parameters(self): # type: () -> Dict[str, str] w = self.params['w'] l = self.params['l'] layer = self.params['layer'] wstr = float_to_si_string(w) lstr = float_to_si_string(l) lay_str = str(layer) return dict(w=wstr, l=lstr, layer=lay_str)
def get_layout_basename(self): # type: () -> str lch_str = float_to_si_string(self.params['lch']) w_str = float_to_si_string(self.params['w']) fg = self.params['fg'] edge_mode = self.params['edge_mode'] basename = 'mdum_l%s_w%s_fg%d_edge%d' % (lch_str, w_str, fg, edge_mode) return basename
def get_layout_basename(self): fmt = 'laygo_%s_l%s_w%s_%s' row_info = self.params['row_info'] sub_type = row_info['sub_type'] th = row_info['threshold'] wstr = float_to_si_string(row_info['w_sub']) lch_unit = row_info['lch_unit'] lstr = float_to_si_string(lch_unit * self.grid.layout_unit * self.grid.resolution) return fmt % (sub_type, lstr, wstr, th)
def get_name_id(self): # type: () -> str """Returns a string identifier representing this resistor core.""" l_str = float_to_si_string(self._layout_info['l']) w_str = float_to_si_string(self._layout_info['w']) res_type = self._layout_info['res_type'] sub_type = self._layout_info['sub_type'] threshold = self._layout_info['threshold'] main = '%s_%s_%s_l%s_w%s' % (res_type, sub_type, threshold, l_str, w_str) return main
def get_layout_basename(self): # type: () -> str lch_str = float_to_si_string(self.params['lch']) w_str = float_to_si_string(self.params['w']) gext = self.params['gate_ext_mode'] basename = 'mdecap_l%s_w%s_fg%d_gext%d_s%d_d%d' % ( lch_str, w_str, self.params['fg'], gext, self.params['sdir'], self.params['ddir']) if self.params['export_gate']: basename += '_gport' return basename
def get_layout_basename(self): fmt = 'ext_b%s_t%s_l%s_w%s_b%s_t%s' bot_mtype = self.params['bot_mtype'] top_mtype = self.params['top_mtype'] bot_thres = self.params['bot_thres'] top_thres = self.params['top_thres'] lstr = float_to_si_string(self.params['lch']) wstr = float_to_si_string(self.params['w']) ans = fmt % (bot_mtype, top_mtype, lstr, wstr, bot_thres, top_thres) if self.params['is_laygo']: ans = 'laygo_' + ans return ans
def get_name_id(self): # type: () -> str """Returns a string identifier representing this resistor core.""" l_str = float_to_si_string(self.params['l']) w_str = float_to_si_string(self.params['w']) res_type = self.params['res_type'] sub_type = self.params['sub_type'] threshold = self.params['threshold'] ext_dir = self.params['ext_dir'] main = '%s_%s_%s_l%s_w%s' % (res_type, sub_type, threshold, l_str, w_str) if ext_dir: main += '_ext%s' % ext_dir return main
def get_layout_basename(self): fmt = '%s_l%s_w%s_%s_lay%d' sub_type = self.params['sub_type'] lstr = float_to_si_string(self.params['lch']) wstr = float_to_si_string(self.params['w']) th = self.params['threshold'] top_layer = self.params['top_layer'] if top_layer is None: top_layer = 0 basename = fmt % (sub_type, lstr, wstr, th, top_layer) if self.params['is_passive']: basename += '_passive' return basename
def get_layout_basename(self): fmt = '%s_l%s_w%s_%s_lay%d_fg%d' sub_type = self.params['sub_type'] lstr = float_to_si_string(self.params['lch']) wstr = float_to_si_string(self.params['w']) fg = self.params['fg'] th = self.params['threshold'] top_layer = self.params['top_layer'] if top_layer is None: top_layer = 0 basename = fmt % (sub_type, lstr, wstr, th, top_layer, fg) return basename
def get_schematic_parameters(self): # type: () -> Dict[str, str] w_res = self.tech_info.tech_params['mos']['width_resolution'] l_res = self.tech_info.tech_params['mos']['length_resolution'] w = self.params['w'] l = self.params['l'] nf = self.params['nf'] wstr = w if isinstance(w, str) else float_to_si_string( int(round(w / w_res)) * w_res) lstr = l if isinstance(l, str) else float_to_si_string( int(round(l / l_res)) * l_res) nstr = nf if isinstance(nf, str) else '%d' % nf return dict(w=wstr, l=lstr, nf=nstr)
def design(self, w=1e-6, l=1e-6, intent='standard'): """Create a physical resistor. Parameters ---------- w : float width of the resistor, in meters. l : float length of the resistor, in meters. intent : str the resistor design intent, i.e. the type of resistor to use. """ self.parameters['w'] = float_to_si_string(w) self.parameters['l'] = float_to_si_string(l) self.parameters['intent'] = intent
def generate(prj, specs): lib_name = 'AAAFOO' params = specs['params'] lch_vmsp_list = specs['swp_params']['lch_vmsp'] gr_nf_list = specs['swp_params']['guard_ring_nf'] temp_db = make_tdb(prj, lib_name, specs) temp_list = [] name_list = [] name_fmt = 'LAYGOBASE_L%s_gr%d' for gr_nf in gr_nf_list: params['guard_ring_nf'] = gr_nf for lch, vm_sp in lch_vmsp_list: config = copy.deepcopy(params['config']) config['lch'] = lch config['tr_spaces'][1] = vm_sp params['config'] = config temp_list.append( temp_db.new_template(params=params, temp_cls=Test, debug=False)) name_list.append(name_fmt % (float_to_si_string(lch), gr_nf)) print('creating layout') temp_db.batch_layout(prj, temp_list, name_list) print('done')
def get_layout_basename(self): """Returns the base name for this template. Returns ------- base_name : str the base name of this template. """ lch_str = float_to_si_string(self.params['lch']) w_str = float_to_si_string(self.params['w']) fg = self.params['fg'] edge_mode = self.params['edge_mode'] basename = 'mdum_l%s_w%s_fg%d_edge%d' % (lch_str, w_str, fg, edge_mode) return basename
def get_layout_basename(self): """Returns the base name for this template. Returns ------- base_name : str the base name of this template. """ lch_str = float_to_si_string(self.params['lch']) w_str = float_to_si_string(self.params['w']) gext = self.params['gate_ext_mode'] basename = 'mdecap_l%s_w%s_fg%d_gext%d_s%d_d%d' % ( lch_str, w_str, self.params['fg'], gext, self.params['sdir'], self.params['ddir']) if self.params['export_gate']: basename += '_gport' return basename
def design(self, res=1e3): """Create an ideal resistor. Parameters ---------- res : float the resistance, in Ohms. """ self.parameters['res'] = float_to_si_string(res)
def design(self, cap=1e-12): """Create an ideal capacitor. Parameters ---------- cap : float the capacitance, in Farads. """ self.parameters['cap'] = float_to_si_string(cap)
def design(self, w=1e-6, l=1e-6, layer=1): """Create a metal resistor. Parameters ---------- w : float the resistor width, in meters. l: float the resistor length, in meters. layer : int the metal layer ID. """ # get technology parameters tech_dict = self.tech_info.tech_params['res_metal'] lib_name = tech_dict['lib_name'] l_name = tech_dict['l_name'] w_name = tech_dict['w_name'] layer_name = tech_dict.get('layer_name', None) cell_name = tech_dict['cell_table'][layer] if layer_name is None: # replace resistor cellview self.replace_instance_master('R0', lib_name, cell_name, static=True) else: self.instances['R0'].parameters[layer_name] = cell_name self.instances['R0'].parameters[l_name] = float_to_si_string( l, precision=6) self.instances['R0'].parameters[w_name] = float_to_si_string( w, precision=6) for key, val in tech_dict['others'].items(): if isinstance(val, float): val = float_to_si_string(val, precision=6) elif isinstance(val, int): val = '%d' % val elif isinstance(val, bool) or isinstance(val, str): pass else: raise ValueError('unsupported type: %s' % type(val)) self.instances['R0'].parameters[key] = val
def get_layout_basename(self): fmt = '%s_end_l%s_%s_lay%d' sub_type = self.params['sub_type'] lstr = float_to_si_string(self.params['lch']) th = self.params['threshold'] top_layer = self.params['top_layer'] basename = fmt % (sub_type, lstr, th, top_layer) if self.params['is_end']: basename += '_end' return basename
def design(self, w=1e-6, l=60e-9, nf=1, intent='standard'): """Create a transistor with the given parameters. Parameters ---------- w : float or int the width/number of fins of this transsitor. l : float the channel length of this transistor. nf : int number of fingers of this transistor. intent : str the design intent of this transistor. In other words, the threshold voltage flavor. """ w_res = self.tech_info.tech_params['mos']['width_resolution'] l_res = self.tech_info.tech_params['mos']['length_resolution'] self.parameters['w'] = float_to_si_string(round(w / w_res) * w_res) self.parameters['l'] = float_to_si_string(round(l / l_res) * l_res) self.parameters['nf'] = nf self.parameters['intent'] = intent
def get_layout_basename(self): lstr = float_to_si_string(self.params['lch']) mos_type = self.params['mos_type'] thres = self.params['threshold'] top_layer = self.params['top_layer'] is_end = self.params['is_end'] fmt = 'laygo_%s_end_l%s_%s_lay%d' basename = fmt % (mos_type, lstr, thres, top_layer) if is_end: basename += '_end' return basename
def get_design_name(self, combo_list): # type: (Sequence[Any, ...]) -> str """Generate cell names based on sweep parameter values.""" name_base = self.specs['dsn_basename'] suffix = '' for var, val in zip(self.swp_var_list, combo_list): if isinstance(val, str): suffix += '_%s_%s' % (var, val) elif isinstance(val, int): suffix += '_%s_%d' % (var, val) elif isinstance(val, float): suffix += '_%s_%s' % (var, float_to_si_string(val)) else: raise ValueError('Unsupported parameter type: %s' % (type(val))) return name_base + suffix
def generate(prj, specs): temp_db = make_tdb(prj, impl_lib, specs) params = specs['params'] lch_list = specs['swp_params']['lch'] gr_nf_list = specs['swp_params']['guard_ring_nf'] temp_list = [] name_list = [] name_fmt = 'DIFFAMP_DIODE_DECAP_L%s_gr%d' for gr_nf in gr_nf_list: for lch in lch_list: params['lch'] = lch params['guard_ring_nf'] = gr_nf temp_list.append( temp_db.new_template(params=params, temp_cls=DiffAmp, debug=False)) name_list.append(name_fmt % (float_to_si_string(lch), gr_nf)) temp_db.batch_layout(prj, temp_list, name_list) print('done')
def generate(prj, specs): temp_db = make_tdb(prj, impl_lib, specs) params = specs['params'] lch_list = specs['swp_params']['lch'] gr_nf_list = specs['swp_params']['guard_ring_nf'] temp_list = [] name_list = [] name_fmt = 'AMPCHAIN_L%s_gr%d' for gr_nf in gr_nf_list: for lch in lch_list: params['lch'] = lch params['guard_ring_nf'] = gr_nf p = dict(amp_params=params) temp_list.append( temp_db.new_template(params=p, temp_cls=AmpChain, debug=False)) name_list.append(name_fmt % (float_to_si_string(lch), gr_nf)) print('creating layout') temp_db.batch_layout(prj, temp_list, name_list) print('done')
def design_dc_bias_sources(self, vbias_dict, ibias_dict, vinst_name, iinst_name, define_vdd=True): # type: (Optional[Dict[str, List[str]]], Optional[Dict[str, List[str]]], str, str, bool) -> None """Convenience function for generating DC bias sources. Given DC voltage/current bias sources information, array the given voltage/current bias sources and configure the voltage/current. Each bias dictionary is a dictionary from bias source name to a 3-element list. The first two elements are the PLUS/MINUS net names, respectively, and the third element is the DC voltage/current value as a string or float. A variable name can be given to define a testbench parameter. Parameters ---------- vbias_dict : Optional[Dict[str, List[str]]] the voltage bias dictionary. None or empty to disable. ibias_dict : Optional[Dict[str, List[str]]] the current bias dictionary. None or empty to disable. vinst_name : str the DC voltage source instance name. iinst_name : str the DC current source instance name. define_vdd : bool True to include a supply voltage source connected to VDD/VSS, with voltage value 'vdd'. """ if define_vdd and 'SUP' not in vbias_dict: vbias_dict = vbias_dict.copy() vbias_dict['SUP'] = ['VDD', 'VSS', 'vdd'] for bias_dict, name_template, param_name, inst_name in \ ((vbias_dict, 'V%s', 'vdc', vinst_name), (ibias_dict, 'I%s', 'idc', iinst_name)): if bias_dict: name_list, term_list, val_list, param_dict_list = [], [], [], [] for name in sorted(bias_dict.keys()): value_tuple = bias_dict[name] pname, nname, bias_val = value_tuple[:3] param_dict = value_tuple[3] if len( value_tuple) > 3 else None term_list.append(dict(PLUS=pname, MINUS=nname)) name_list.append(name_template % name) param_dict_list.append(param_dict) if isinstance(bias_val, str): val_list.append(bias_val) elif isinstance(bias_val, int) or isinstance( bias_val, float): val_list.append(float_to_si_string(bias_val)) else: raise ValueError('value %s of type %s not supported' % (bias_val, type(bias_val))) self.array_instance(inst_name, name_list, term_list=term_list) for inst, val, param_dict in zip(self.instances[inst_name], val_list, param_dict_list): inst.parameters[param_name] = val if param_dict is not None: for k, v in param_dict.items(): if isinstance(v, str): pass elif isinstance(v, int) or isinstance(v, float): v = float_to_si_string(v) else: raise ValueError( 'value %s of type %s not supported' % (v, type(v))) inst.parameters[k] = v else: self.delete_instance(inst_name)