Source code for bag3_magnetics.layout.inductor.ind_wrap

# -*- coding: utf-8 -*-
from typing import Mapping, Any, Optional, Type

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

from pybag.core import Transform

from .util import IndTemplate
from .ind_core import IndCore
from .ind_ring import IndRing
from ...schematic.ind_wrap import bag3_magnetics__ind_wrap


[docs]class IndWrap(IndTemplate): """A wrapper for Inductor.""" def __init__(self, temp_db: TemplateDB, params: Param, **kwargs: Any) -> None: IndTemplate.__init__(self, temp_db, params, **kwargs) @classmethod
[docs] def get_schematic_class(cls) -> Optional[Type[Module]]: return bag3_magnetics__ind_wrap
@classmethod
[docs] def get_params_info(cls) -> Mapping[str, str]: return dict( lay_id='Inductor top layer ID', bot_lay_id='Inductor bot layer ID; same as top layer by default', n_turns='Number of turns; 1 by default', width='Metal width for inductor turns', spacing='Metal spacing between inductor turns', radius_x='radius along X-axis', radius_y='radius along Y-axis', term_sp='Spacing between inductor terminals', ind_shape='"Rectangle" or "Octagon"; "Octagon" by default', w_ring='True to have guard ring, False by default', ring_specs='Specs for guard ring, Optional', w_fill='True to have metal fill', fill_specs='Specs for metal fill',
) @classmethod
[docs] def get_default_param_values(cls) -> Mapping[str, Any]: return dict( bot_lay_id=-1, n_turns=1, ind_shape='Octagon', w_ring=False, ring_specs=None, w_fill=False, fill_specs=None,
)
[docs] def draw_layout(self) -> None: lay_id: int = self.params['lay_id'] bot_lay_id: int = self.params['bot_lay_id'] if bot_lay_id < 1: bot_lay_id = lay_id if bot_lay_id < lay_id: n_turns = 2 else: n_turns: int = self.params['n_turns'] width: int = self.params['width'] spacing: int = self.params['spacing'] radius_x: int = self.params['radius_x'] radius_y: int = self.params['radius_y'] term_sp: int = self.params['term_sp'] ind_shape: str = self.params['ind_shape'] w_ring: bool = self.params['w_ring'] ring_specs: Optional[Mapping[str, Any]] = self.params['ring_specs'] w_fill: bool = self.params['w_fill'] fill_specs: Optional[Mapping[str, Any]] = self.params['fill_specs'] # make inductor core core_params = dict( lay_id=lay_id, bot_lay_id=bot_lay_id, n_turns=n_turns, width=width, spacing=spacing, radius_x=radius_x, radius_y=radius_y, term_sp=term_sp, ind_shape=ind_shape, ) core_master: IndCore = self.new_template(IndCore, params=core_params) # make inductor guard ring if w_ring: ring_width: int = ring_specs['width'] ring_spacing: int = ring_specs['spacing'] ring_sup: str = ring_specs.get('ring_sup', 'VSS') ring_params = dict( lay_id=lay_id, bot_lay_id=bot_lay_id, width=ring_width, gap=term_sp + 2 * width + 2 * ring_spacing + ring_width, radius_x=radius_x + width // 2 + ring_spacing + ring_width // 2, radius_y=radius_y + width // 2 + ring_spacing + ring_width // 2, ring_sup=ring_sup, ring_pin_w=term_sp + 2 * width, ) dx = dy = ring_width + ring_spacing ring_master: IndRing = self.new_template(IndRing, params=ring_params) ring_inst = self.add_instance(ring_master, inst_name='XRING') self.reexport(ring_inst.get_port(ring_sup)) ring_turn_coords = ring_master.turn_coords self._actual_bbox = ring_master.actual_bbox else: ring_width = 0 ring_sup = '' ring_turn_coords = [] dx = dy = 0 self._actual_bbox = core_master.actual_bbox # place inductor core self.add_instance(core_master, inst_name='XCORE', xform=Transform(dx=dx, dy=dy)) # draw leads term_coords = [] for _coord in core_master.term_coords: term_coords.append((_coord[0] + dx, _coord[1] + dy)) res1_l = width // 2 res2_l = width // 4 term0, term1 = self._draw_leads(lay_id, width, term_coords, res1_l, res2_l) # add pins lp = self.grid.tech_info.get_lay_purp_list(lay_id)[0] self.add_pin_primitive('P1', lp[0], term0) self.add_pin_primitive('P2', lp[0], term1) # draw fill if ind_shape == 'Rectangle': n_sides = 4 elif ind_shape == 'Octagon': n_sides = 8 else: raise ValueError(f'Unknown ind_shape={ind_shape}. Use "Rectangle" or "Octagon".') if w_fill: for _specs in fill_specs: self._draw_fill(n_sides, _specs, core_master.turn_coords, width, dx, dy, ring_turn_coords, ring_width) # 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 = dict( res1_l=res1_l, res2_l=res2_l, res_w=width, res_layer=lay_id, w_ring=w_ring, ring_sup=ring_sup,
)