Source code for bag3_magnetics.layout.inductor_spiral.ind_spiral_wrap

from typing import Mapping, Any, Optional, Type

from bag.layout.template import TemplateDB
from bag.util.immutable import Param
from bag.layout.util import BBox
from bag.design.module import Module

from pybag.core import Transform

from .util import IndSpiralTemplate
from .ind_spiral import IndSpiral
from .ind_interleave import IndInterleave
from .ind_spiral_ring import IndSpiralRing
from ...schematic.ind_spiral_wrap import bag3_magnetics__ind_spiral_wrap
from ...schematic.ind_interleave_wrap import bag3_magnetics__ind_interleave_wrap


[docs]class IndWrap(IndSpiralTemplate): """A wrapper for spiral Inductor.""" def __init__(self, temp_db: TemplateDB, params: Param, **kwargs: Any) -> None: IndSpiralTemplate.__init__(self, temp_db, params, **kwargs) @classmethod
[docs] def get_params_info(cls) -> Mapping[str, str]: return dict( n_turns='Number of turns; 1 by default', lay_id='Inductor layer ID', bot_lay_id='Inductor bottom layer ID', radius='Outermost radius', width='Width of inductor sides', spacing='Spacing between inductor turns', interleave='True to leave space between spiral turns for interleaving; False by default', lead_width='Width of inductor leads', lead_spacing='Spacing between inductor leads', w_ring='True to have guard ring, False by default', ring_specs='Specs for guard ring, Optional',
) @classmethod
[docs] def get_default_param_values(cls) -> Mapping[str, Any]: return dict( n_turns=1, bot_lay_id=-1, interleave=False, w_ring=False, ring_specs=None,
)
[docs] def draw_layout(self) -> None: n_turns: int = self.params['n_turns'] lay_id: int = self.params['lay_id'] bot_lay_id: int = self.params['bot_lay_id'] radius: int = self.params['radius'] width: int = self.params['width'] spacing: int = self.params['spacing'] interleave: bool = self.params['interleave'] lead_width: int = self.params['lead_width'] lead_spacing: int = self.params['lead_spacing'] w_ring: bool = self.params['w_ring'] ring_specs: Optional[Mapping[str, Any]] = self.params['ring_specs'] # make core core_params = dict( n_turns=n_turns, lay_id=lay_id, radius=radius, width=width, spacing=spacing, lead_width=lead_width, lead_spacing=lead_spacing, ) if interleave: core_master: IndInterleave = self.new_template(IndInterleave, params=core_params) else: core_params['bot_lay_id'] = bot_lay_id core_master: IndSpiral = self.new_template(IndSpiral, params=core_params) sch_params = dict(**core_master.sch_params, w_ring=w_ring) # make inductor guard ring if w_ring: ring_width: int = ring_specs['width'] ring_spacing: int = ring_specs['spacing'] ring_params = dict( lay_id=lay_id, bot_lay_id=bot_lay_id, width=ring_width, gap=lead_spacing + 2 * lead_width + 2 * ring_spacing + ring_width, radius=radius + width // 2 + ring_spacing + ring_width // 2, ) dx = dy = ring_width + ring_spacing ring_master: IndSpiralRing = self.new_template(IndSpiralRing, params=ring_params) ring_inst = self.add_instance(ring_master, inst_name='XRING') if interleave: self.reexport(ring_inst.get_port('ref0'), hide=False) self.reexport(ring_inst.get_port('ref1'), hide=False) else: self.reexport(ring_inst.get_port('ref_p'), hide=False) self.reexport(ring_inst.get_port('ref_m'), hide=False) self._actual_bbox = ring_master.actual_bbox else: dx = dy = 0 self._actual_bbox = core_master.actual_bbox # place core core = self.add_instance(core_master, inst_name='XCORE', xform=Transform(dx=dx, dy=dy)) if interleave: port_lay_id = lay_id - 1 self._extend_lead_vert(core.get_pin('plus0'), -1, self._actual_bbox.yl, port_lay_id, 'plus0') self._extend_lead_vert(core.get_pin('minus1'), -1, self._actual_bbox.yl, port_lay_id, 'minus1') self._extend_lead_vert(core.get_pin('plus1'), 1, self._actual_bbox.yh, port_lay_id, 'plus1') self._extend_lead_vert(core.get_pin('minus0'), 1, self._actual_bbox.yh, port_lay_id, 'minus0') else: self._extend_lead_vert(core.get_pin('plus'), -1, self._actual_bbox.yl, lay_id, 'plus') self._extend_lead_vert(core.get_pin('minus'), -1, self._actual_bbox.yl, bot_lay_id, 'minus') # add inductor ID layer id_lp = self.grid.tech_info.tech_params['inductor'].get('id_lp', []) for _lp in id_lp: self.add_rect(_lp, self._actual_bbox) # set size self.set_size_from_bound_box(lay_id, self._actual_bbox, round_up=True) # get schematic parameters self.sch_params = sch_params
[docs] def _extend_lead_vert(self, lead_bbox: BBox, direction: int, y_targ: int, lay_id: int, name: str) -> None: lp = self.grid.tech_info.get_lay_purp_list(lay_id)[0] _h = lead_bbox.h if direction == 1: # extend up rect_bbox = BBox(lead_bbox.xl, lead_bbox.yh, lead_bbox.xh, y_targ) pin_bbox = BBox(lead_bbox.xl, y_targ - _h, lead_bbox.xh, y_targ) elif direction == -1: # extend down rect_bbox = BBox(lead_bbox.xl, y_targ, lead_bbox.xh, lead_bbox.yl) pin_bbox = BBox(lead_bbox.xl, y_targ, lead_bbox.xh, y_targ + _h) else: raise ValueError(f'Unknown direction={direction}. Use -1 or +1.') self.add_rect(lp, rect_bbox) self.add_pin_primitive(name, lp[0], pin_bbox)
[docs]class IndSpiralWrap(IndWrap): @classmethod
[docs] def get_schematic_class(cls) -> Optional[Type[Module]]: return bag3_magnetics__ind_spiral_wrap
[docs]class IndInterleaveWrap(IndWrap): @classmethod
[docs] def get_schematic_class(cls) -> Optional[Type[Module]]: return bag3_magnetics__ind_interleave_wrap