Source code for bag3_analog.layout.res_diff

"""This module defines differential resistors."""

from typing import Mapping, Any, Optional, Type, cast

from bag.util.immutable import Param
from bag.design.module import Module
from bag.layout.template import TemplateDB
from bag.layout.routing.base import TrackManager, WireArray

from xbase.layout.res.base import ResBasePlaceInfo, ResArrayBase

from ..schematic.res_diff import bag3_analog__res_diff


[docs]class ResDiff(ResArrayBase): def __init__(self, temp_db: TemplateDB, params: Param, **kwargs: Any) -> None: ResArrayBase.__init__(self, temp_db, params, **kwargs) @classmethod
[docs] def get_schematic_class(cls) -> Optional[Type[Module]]: return bag3_analog__res_diff
@classmethod
[docs] def get_params_info(cls) -> Mapping[str, str]: return dict( pinfo='The ResBasePlaceInfo object.', nx_dum='Number of dummies on each side, X direction', ny_dum='Number of dummies on each side, Y direction',
) @classmethod
[docs] def get_default_param_values(cls) -> Mapping[str, Any]: return dict(nx_dum=0, ny_dum=0)
[docs] def draw_layout(self) -> None: pinfo = cast(ResBasePlaceInfo, ResBasePlaceInfo.make_place_info(self.grid, self.params['pinfo'])) self.draw_base(pinfo) # Get hm_layer and vm_layer WireArrays warrs, bulk_warrs = self.connect_hm_vm() # Connect all dummies self.connect_dummies(warrs, bulk_warrs) unit_params = dict( w=pinfo.w_res, l=pinfo.l_res, intent=pinfo.res_type, ) nx, ny = pinfo.nx, pinfo.ny nx_dum: int = self.params['nx_dum'] ny_dum: int = self.params['ny_dum'] npar_tot = nx - 2 * nx_dum nser = ny - 2 * ny_dum assert npar_tot & 1 == 0, f'nx - 2 * nx_dum = {npar_tot} should be even.' num_dum = nx * ny - npar_tot * nser # --- Routing of unit resistors --- # hm_layer = self.conn_layer + 1 vm_layer = hm_layer + 1 xm_layer = vm_layer + 1 ym_layer = xm_layer + 1 xxm_layer = ym_layer + 1 # make 2 resistors out of all the resistor units rp_bot, rp_top = self.connect_units(warrs, nx_dum, nx // 2, ny_dum, ny - ny_dum) rm_bot, rm_top = self.connect_units(warrs, nx // 2, nx - nx_dum, ny_dum, ny - ny_dum) # Supply connections on xxm_layer sub_type = cast(ResBasePlaceInfo, self.place_info).res_config['sub_type_default'] sup_top0 = self.connect_via_stack(self.tr_manager, bulk_warrs[vm_layer][0], xxm_layer, 'sup') sup_top1 = self.connect_via_stack(self.tr_manager, bulk_warrs[vm_layer][1], xxm_layer, 'sup') sup_name = 'VDD' if sub_type == 'ntap' else 'VSS' self.add_pin(sup_name, self.connect_wires([sup_top0, sup_top1])[0]) # connect XRP and XRM from vm_layer to xxm_layer for _bot, _top, _suf in [(rp_bot, rp_top, 'p'), (rm_bot, rm_top, 'm')]: _in = self.connect_stack(self.tr_manager, _bot, xxm_layer, 'sig', xm_layer) _out = self.connect_stack(self.tr_manager, _top, xxm_layer, 'sig', xm_layer) self.add_pin(f'{_suf}_in', _in) self.add_pin(f'{_suf}_out', _out) self.sch_params = dict( load_params=dict( unit_params=unit_params, nser=nser, npar=npar_tot // 2, ), dum_params=dict( unit_params=unit_params, nser=1, npar=num_dum, ), sub_type=sub_type,
)
[docs] def connect_stack(self, tr_manager: TrackManager, warr: WireArray, top_layer: int, w_type: str = 'sig', mid_layer: int = -1): # this is different from connect_via_stack() as it does not connect the intermediate wires to reduce cap top_warr = [] for _warr in warr.warr_iter(): _mid = self.connect_via_stack(tr_manager, _warr, mid_layer, w_type) top_warr.append(self.connect_via_stack(tr_manager, _mid, top_layer, w_type)) return self.connect_wires(top_warr)[0]