Esempio n. 1
0
def test_move_by_orient(coords: Tuple[int, int, int, int], orient: Orient2D, dt: int, dp: int,
                        ecoords: Tuple[int, int, int, int]) -> None:
    box = BBox(coords[0], coords[1], coords[2], coords[3])
    expect = BBox(ecoords[0], ecoords[1], ecoords[2], ecoords[3])

    box.move_by_orient(orient, dt, dp)
    assert box == expect
Esempio n. 2
0
    def get_mos_ext_edge_info(self, blk_w: int, einfo: MOSEdgeInfo) -> LayoutInfo:
        sd_pitch = self.sd_pitch

        cpo_h = self.mos_config['cpo_h']

        mos_lay_table = self.tech_info.config['mos_lay_table']
        cpo_lp = mos_lay_table['CPO']
        po_lp = mos_lay_table['PO_DUMMY']

        blk_h = einfo['blk_h']
        row_type = einfo['row_type']
        mos_type = einfo['mos_type']
        threshold = einfo['threshold']

        blk_rect = BBox(0, 0, blk_w, blk_h)
        imp_rect = BBox(blk_w - sd_pitch, 0, blk_w, blk_h)
        cpo_h2 = cpo_h // 2

        builder = LayoutInfoBuilder()
        builder.add_rect_arr(cpo_lp, BBox(blk_w - sd_pitch, -cpo_h2, blk_w, cpo_h2))
        builder.add_rect_arr(cpo_lp, BBox(blk_w - sd_pitch, blk_h - cpo_h2, blk_w, blk_h + cpo_h2))
        num_sd_pitch = blk_w // sd_pitch
        self._add_po_array(builder, po_lp, (0, blk_h), num_sd_pitch - 1, num_sd_pitch)

        self._add_fb(builder, imp_rect)

        for lay_purp in self._thres_imp_well_layers_iter(row_type, mos_type, threshold):
            builder.add_rect_arr(lay_purp, imp_rect)

        return builder.get_info(blk_rect)
Esempio n. 3
0
    def _get_mos_ext_info_helper(self, num_cols: int, blk_h: int, row_type: MOSType, threshold: str
                                 ) -> ExtEndLayInfo:
        sd_pitch = self.sd_pitch

        cpo_h = self.mos_config['cpo_h']

        mos_lay_table = self.tech_info.config['mos_lay_table']
        cpo_lp = mos_lay_table['CPO']
        po_lp = mos_lay_table['PO_DUMMY']

        blk_w = num_cols * sd_pitch
        cpo_h2 = cpo_h // 2
        blk_rect = BBox(0, 0, blk_w, blk_h)

        builder = LayoutInfoBuilder()
        builder.add_rect_arr(cpo_lp, BBox(0, -cpo_h2, blk_w, cpo_h2))
        builder.add_rect_arr(cpo_lp, BBox(0, blk_h - cpo_h2, blk_w, blk_h + cpo_h2))

        self._add_fb(builder, blk_rect)
        self._add_po_array(builder, po_lp, (0, blk_h), 0, num_cols)

        for lay_purp in self._thres_imp_well_layers_iter(row_type, row_type, threshold):
            builder.add_rect_arr(lay_purp, blk_rect)

        edge_info = MOSEdgeInfo(blk_h=blk_h, row_type=row_type, mos_type=row_type,
                                threshold=threshold)
        return ExtEndLayInfo(builder.get_info(blk_rect), edge_info)
def add_base(builder: LayoutInfoBuilder,
             row_type: MOSType,
             threshold: str,
             imp_y: Tuple[int, int],
             rect: BBox,
             well_x: Optional[Tuple[int, int]] = None) -> None:
    if rect.is_physical():
        if not row_type.is_pwell:
            well_lp = ('nwell', 'drawing')
            if well_x is None:
                builder.add_rect_arr(well_lp, rect)
            else:
                builder.add_rect_arr(
                    well_lp, BBox(well_x[0], rect.yl, well_x[1], rect.yh))

        if row_type.is_n_plus:
            builder.add_rect_arr(('nsdm', 'drawing'), rect)
        else:
            pimp_lp = ('psdm', 'drawing')
            nimp_lp = ('nsdm', 'drawing')
            if rect.yl < imp_y[0]:
                builder.add_rect_arr(nimp_lp,
                                     BBox(rect.xl, rect.yl, rect.xh, imp_y[0]))
            if imp_y[1] < rect.yh:
                builder.add_rect_arr(nimp_lp,
                                     BBox(rect.xl, imp_y[1], rect.xh, rect.yh))
            if imp_y[0] < imp_y[1]:
                builder.add_rect_arr(
                    pimp_lp, BBox(rect.xl, imp_y[0], rect.xh, imp_y[1]))

        thres_lp = _get_thres_lp(row_type, threshold)
        if thres_lp[0] != '':
            builder.add_rect_arr(thres_lp, rect)
Esempio n. 5
0
def test_transform(box0, dx, dy, orient, box1):
    xform = Transform(dx, dy, Orientation[orient])
    a = BBox(box0[0], box0[1], box0[2], box0[3])
    ans = BBox(box1[0], box1[1], box1[2], box1[3])

    b = a.get_transform(xform)
    assert b == ans
    assert b is not a
    c = a.transform(xform)
    assert a == ans
    assert c is a
Esempio n. 6
0
def test_insert():
    rtree = RTree()

    box_list = [BBox(0, 0, 2, 3), BBox(-2, -3, 0, -1)]
    items = [None, {'hi': 2, 'bye': 'foo'}]

    for obj, box in zip(items, box_list):
        rtree.insert(obj, box)

    for box, obj_id in rtree:
        assert rtree[obj_id] is items[obj_id]
        assert box == box_list[obj_id]
Esempio n. 7
0
def test_overlap():
    rtree = RTree()

    box_list = [BBox(0, 0, 2, 3), BBox(-2, -3, 0, -1), BBox(10, 10, 20, 15)]
    test_box = BBox(-1, -2, 0, 0)

    for box in box_list:
        rtree.insert(None, box)

    obj_list = list(rtree.overlap_iter(test_box))
    assert len(obj_list) == 1
    assert obj_list[0][0] == box_list[1]
Esempio n. 8
0
    def get_bounding_box(self,
                         grid: RoutingGrid,
                         layer: Union[int, str] = -1000) -> BBox:
        """Calculate the overall bounding box of this port on the given layer.

        Parameters
        ----------
        grid : RoutingGrid
            the RoutingGrid of this Port.
        layer : Union[int, str]
            the layer ID.  If Negative, check if this port is on a single layer,
            then return the result.

        Returns
        -------
        bbox : BBox
            the bounding box.
        """
        layer = self._get_layer(layer)
        box = BBox.get_invalid_bbox()
        for geo in self._pin_dict[layer]:
            if isinstance(geo, BBox):
                box.merge(geo)
            else:
                box.merge(grid.get_warr_bbox(geo))
        return box
Esempio n. 9
0
    def get_warr_bbox(self, warr: WireArray) -> BBox:
        """Computes the overall bounding box of the given WireArray.

        Parameters
        ----------
        warr : WireArray
            the WireArray object.

        Returns
        -------
        bbox : BBox
            the overall bounding box of the WireArray.
        """
        tid = warr.track_id
        layer_id = tid.layer_id
        lower, upper = self.get_wire_bounds_htr(layer_id, tid.base_htr,
                                                tid.width)

        delta = (tid.num - 1) * int(tid.pitch * self.get_track_pitch(layer_id))
        if delta >= 0:
            upper += delta
        else:
            lower += delta

        return BBox(self.get_direction(layer_id), warr.lower, warr.upper,
                    lower, upper)
Esempio n. 10
0
def test_properties(xl, yl, xh, yh, physical, valid):
    ans = BBox(xl, yl, xh, yh)
    assert ans.xl == xl
    assert ans.yl == yl
    assert ans.xh == xh
    assert ans.yh == yh
    assert ans.xm == (xl + xh) // 2
    assert ans.ym == (yl + yh) // 2
    assert ans.w == xh - xl
    assert ans.h == yh - yl
    assert ans.get_immutable_key() == (xl, yl, xh, yh)
    assert ans.get_dim(Orient2D.x) == ans.w
    assert ans.get_dim(Orient2D.y) == ans.h
    assert ans.get_interval(Orient2D.x) == (xl, xh)
    assert ans.get_interval(Orient2D.y) == (yl, yh)
    """
Esempio n. 11
0
def test_pop():
    rtree = RTree()

    box_list = [BBox(0, 0, 2, 3), BBox(-2, -3, 0, -1), BBox(10, 10, 20, 15)]

    for box in box_list:
        rtree.insert(None, box)

    ans = rtree.pop(1)
    assert ans is None

    results = list(rtree)
    assert len(results) == 2
    for box, obj_id in results:
        assert obj_id != 1
        assert box == box_list[obj_id]
Esempio n. 12
0
 def _add_vg_half(vg_x: int) -> None:
     xl = vg_x - mp_delta
     xr = vg_x + mp_delta
     builder.add_rect_arr(mp_lp, BBox(xl, mp_yb, xr, mp_yt),
                          nx=num_vg2, spx=vg_pitch)
     builder.add_via(g_info.get_via_info('M1_LiPo', vg_x, mp_yc, mp_h,
                                         nx=num_vg2, spx=vg_pitch))
Esempio n. 13
0
    def merge_well(self,
                   template: TemplateBase,
                   inst_list: List[PyLayInstance],
                   sub_type: str,
                   *,
                   threshold: str = '',
                   res_type: str = '',
                   merge_imp: bool = False) -> None:
        """Merge the well of the given instances together."""

        if threshold is not None:
            lay_iter = chain(
                self.get_well_layers(sub_type),
                self.get_threshold_layers(sub_type,
                                          threshold,
                                          res_type=res_type))
        else:
            lay_iter = self.get_well_layers(sub_type)
        if merge_imp:
            lay_iter = chain(
                lay_iter, self.get_implant_layers(sub_type, res_type=res_type))

        for lay_purp in lay_iter:
            tot_box = BBox.get_invalid_bbox()
            for inst in inst_list:
                cur_box = inst.master.get_rect_bbox(lay_purp)
                tot_box.merge(inst.transform_master_object(cur_box))
            if tot_box.is_physical():
                template.add_rect(lay_purp, tot_box)
Esempio n. 14
0
    def get_mos_corner_info(self, blk_w: int, blk_h: int, einfo: MOSEdgeInfo) -> CornerLayInfo:
        sd_pitch = self.sd_pitch

        cpo_h = self.mos_config['cpo_h']

        mos_lay_table = self.tech_info.config['mos_lay_table']
        cpo_lp = mos_lay_table['CPO']

        cpo_h2 = cpo_h // 2
        blk_rect = BBox(0, 0, blk_w, blk_h)

        builder = LayoutInfoBuilder()
        builder.add_rect_arr(cpo_lp,
                             BBox(blk_w - sd_pitch, blk_h - cpo_h2, blk_w, blk_h + cpo_h2))

        edgel = edgeb = ImmutableSortedDict(dict(dev_type=DeviceType.MOS, well_margin=sd_pitch))
        return CornerLayInfo(builder.get_info(blk_rect), (0, 0), edgel, edgeb)
Esempio n. 15
0
    def _get_mos_active_rect_list(self, builder: LayoutInfoBuilder,
                                  row_info: MOSRowInfo, fg: int, w: int,
                                  dev_type: MOSType) -> BBox:
        lch = self.lch
        sd_pitch = self.sd_pitch
        od_po_extx = self.od_po_extx
        md_w: int = self.mos_config['md_w']

        row_type = row_info.row_type
        blk_yt = row_info.height

        od_yb: int = row_info['od_yb']
        md_y: Tuple[int, int] = row_info['md_y']

        mos_lay_table = self.tech_info.config['mos_lay_table']
        od_lp = mos_lay_table['OD']
        po_lp = mos_lay_table['PO']
        md_lp = mos_lay_table['MD']

        blk_xr = fg * sd_pitch
        po_x0 = (sd_pitch - lch) // 2
        od_yt = od_yb + self.get_od_height(w)

        # draw PO
        self._add_po_array(builder, po_lp, (0, blk_yt), 0, fg)
        # draw OD
        od_sd_dx = od_po_extx - po_x0
        od_xl = -od_sd_dx
        od_xr = fg * sd_pitch + od_sd_dx
        builder.add_rect_arr(od_lp, BBox(od_xl, od_yb, od_xr, od_yt))
        # draw MD
        md_x0 = -md_w // 2
        builder.add_rect_arr(md_lp,
                             BBox(md_x0, md_y[0], md_x0 + md_w, md_y[1]),
                             nx=fg + 1,
                             spx=sd_pitch)
        # draw threshold and implant layers
        blk_rect = BBox(0, 0, blk_xr, blk_yt)
        blk_box = BBox(0, 0, blk_xr, blk_yt)
        for lay_purp in self._thres_imp_well_layers_iter(
                row_type, dev_type, row_info.threshold):
            builder.add_rect_arr(lay_purp, blk_box)

        self._add_fb(builder, blk_rect)

        return blk_rect
Esempio n. 16
0
    def get_mos_end_info(self, blk_h: int, num_cols: int, einfo: RowExtInfo) -> ExtEndLayInfo:
        sd_pitch = self.sd_pitch

        cpo_h = self.mos_config['cpo_h']

        mos_lay_table = self.tech_info.config['mos_lay_table']
        cpo_lp = mos_lay_table['CPO']

        cpo_h2 = cpo_h // 2
        blk_w = num_cols * sd_pitch

        blk_rect = BBox(0, 0, blk_w, blk_h)

        builder = LayoutInfoBuilder()
        builder.add_rect_arr(cpo_lp, BBox(0, blk_h - cpo_h2, blk_w, blk_h + cpo_h2))

        edge_info = MOSEdgeInfo()
        return ExtEndLayInfo(builder.get_info(blk_rect), edge_info)
Esempio n. 17
0
    def _add_po_array(self, builder: LayoutInfoBuilder, po_lp: Tuple[str, str],
                      po_y: Tuple[int, int], start: int, stop: int) -> None:
        lch = self.lch
        sd_pitch = self.sd_pitch

        po_x0 = (sd_pitch - lch) // 2 + sd_pitch * start
        fg = stop - start
        builder.add_rect_arr(po_lp, BBox(po_x0, po_y[0], po_x0 + lch, po_y[1]),
                             nx=fg, spx=sd_pitch)
Esempio n. 18
0
    def _add_fb(self, builder: LayoutInfoBuilder, rect: BBox) -> None:
        fin_h = self.fin_h
        fin_p = self.mos_config['fin_p']

        mos_lay_table = self.tech_info.config['mos_lay_table']
        fb_lp = mos_lay_table['FB']

        dy = (fin_p + fin_h) // 2
        builder.add_rect_arr(fb_lp, BBox(rect.xl, rect.yl - dy, rect.xh, rect.yh + dy))
Esempio n. 19
0
    def draw_layout(self):
        w: int = self.params['w']
        h: int = self.params['h']
        fill_layer: int = self.params['fill_layer']

        grid = self.grid
        tech_info = grid.tech_info
        fill_info = tech_info.get_max_space_fill_info(fill_layer)

        self.set_size_from_bound_box(fill_layer,
                                     BBox(0, 0, w, h),
                                     round_up=True)
        bbox = self.bound_box

        tdir = grid.get_direction(fill_layer)
        pdir = tdir.perpendicular()
        margin = fill_info.get_margin(pdir)
        margin_le = fill_info.get_margin(tdir)
        dim = bbox.get_dim(pdir)
        dim_le = bbox.get_dim(tdir)

        wlen = grid.get_min_cont_length(fill_layer, 1)

        # fill edges and ends
        tidxl = grid.coord_to_track(fill_layer,
                                    margin,
                                    mode=RoundMode.LESS_EQ,
                                    even=True)
        tidxr = grid.coord_to_track(fill_layer,
                                    dim - margin,
                                    mode=RoundMode.GREATER_EQ,
                                    even=True)

        tcoord_u = dim_le - margin_le
        num = tidxr - tidxl - 1
        self.add_wires(fill_layer,
                       tidxl,
                       margin_le,
                       tcoord_u,
                       num=2,
                       pitch=tidxr - tidxl)
        self.add_wires(fill_layer,
                       tidxl + 1,
                       margin_le,
                       margin_le + wlen,
                       num=num,
                       pitch=1)
        self.add_wires(fill_layer,
                       tidxl + 1,
                       tcoord_u - wlen,
                       tcoord_u,
                       num=num,
                       pitch=1)

        self.do_max_space_fill(fill_layer, bbox)
Esempio n. 20
0
    def get_ext_geometries(self, re_bot: RowExtInfo, re_top: RowExtInfo,
                           be_bot: ImmutableList[BlkExtInfo], be_top: ImmutableList[BlkExtInfo],
                           cut_mode: MOSCutMode, bot_exty: int, top_exty: int,
                           dx: int, dy: int, w_edge: int) -> LayoutInfo:
        builder = LayoutInfoBuilder()

        if cut_mode is MOSCutMode.MID:
            sd_pitch = self.sd_pitch

            cpo_h = self.mos_config['cpo_h']
            cpo_h2 = cpo_h // 2

            cpo_lp = self.tech_info.config['mos_lay_table']['CPO']

            wr = dx
            for be in be_bot:
                wr += be.fg * sd_pitch
            builder.add_rect_arr(cpo_lp, BBox(dx - sd_pitch, dy - cpo_h2,
                                              wr + sd_pitch, dy + cpo_h2))

        return builder.get_info(BBox(0, 0, 0, 0))
Esempio n. 21
0
    def draw_layout(self):
        fill_layer: int = self.params['fill_layer']

        grid = self.grid
        tech_info = grid.tech_info
        fill_info = tech_info.get_max_space_fill_info(fill_layer)

        tdir = grid.get_direction(fill_layer)
        pdir = tdir.perpendicular()
        margin = fill_info.get_margin(pdir)
        margin_le = fill_info.get_margin(tdir)
        sp_le = fill_info.get_space(tdir)

        blk_arr = grid.get_block_size(fill_layer,
                                      half_blk_x=False,
                                      half_blk_y=False)
        dim_q = blk_arr[pdir.value]

        w = (int(round(margin * 1.5)) // dim_q) * dim_q
        wlen = grid.get_min_cont_length(fill_layer, 1)
        h = 2 * margin_le + 7 * wlen + 5 * sp_le

        self.set_size_from_bound_box(fill_layer,
                                     BBox(0, 0, w, h),
                                     round_up=True,
                                     half_blk_x=False,
                                     half_blk_y=False)
        bbox = self.bound_box

        dim = bbox.get_dim(pdir)

        tidx0 = grid.find_next_track(fill_layer,
                                     dim - margin,
                                     mode=RoundMode.LESS)
        tidx1 = grid.find_next_track(fill_layer,
                                     margin,
                                     mode=RoundMode.GREATER)
        tidx_l = tidx0 + 1
        tidx_r = tidx1 - 1

        lower = margin_le
        self.add_wires(fill_layer, tidx0, lower, lower + wlen)
        self.add_wires(fill_layer, tidx1, lower, lower + wlen)
        lower += wlen + sp_le
        self.add_wires(fill_layer, tidx1, lower, lower + wlen)
        lower += wlen + sp_le
        self.add_wires(fill_layer, tidx0, lower, lower + wlen)
        lower += 2 * wlen + 2 * sp_le
        self.add_wires(fill_layer, tidx_l, lower, lower + wlen)
        lower += 2 * wlen + sp_le
        self.add_wires(fill_layer, tidx_r, lower, lower + wlen)

        self.do_max_space_fill(fill_layer, bbox)
Esempio n. 22
0
def test_constructor(box_data, nx, ny, spx, spy):
    base = BBox(*box_data)
    ref = BBoxArray(base, nx, ny, spx, spy)
    assert ref.base == base
    assert ref.nx == nx
    assert ref.ny == ny
    assert ref.spx == spx
    assert ref.spy == spy

    a1 = BBoxArray(base, Orient2D.x, nx, spx, ny, spy)
    a2 = BBoxArray(base, Orient2D.y, ny, spy, nx, spx)
    assert a1 == ref
    assert a2 == ref
Esempio n. 23
0
def test_merge_invalid():
    a = BBox(0, 0, 2, 3)
    b = BBox(100, 103, 200, 102)

    a2 = a.get_merge(b)
    a3 = b.get_merge(a)
    assert a2 == a
    assert a3 == a
    assert a2 is not a
    assert a3 is not a

    a2 = a.merge(b)
    assert a2 is a
    b2 = b.merge(a)
    assert b2 is b
    assert b2 == a
Esempio n. 24
0
    def get_mos_row_edge_info(self, blk_w: int, rinfo: MOSRowInfo,
                              einfo: MOSEdgeInfo) -> LayoutInfo:
        lch = self.lch
        sd_pitch = self.sd_pitch
        od_po_extx = self.od_po_extx
        od_extx = od_po_extx - (sd_pitch - lch) // 2

        mos_config = self.mos_config
        imp_od_encx: int = mos_config['imp_od_encx']

        mos_lay_table = self.tech_info.config['mos_lay_table']

        row_type = rinfo.row_type
        blk_h = rinfo.height

        mos_type = einfo['mos_type']
        has_od = einfo.get('has_od', False)

        blk_rect = BBox(0, 0, blk_w, blk_h)
        imp_rect = BBox(blk_w - imp_od_encx - od_extx, 0, blk_w, blk_h)
        po_xl = blk_w - sd_pitch // 2 - lch // 2
        builder = LayoutInfoBuilder()
        if has_od:
            po_lp = mos_lay_table['PO_PODE']
        else:
            po_lp = mos_lay_table['PO_DUMMY']

        builder.add_rect_arr(po_lp, BBox(po_xl, 0, po_xl + lch, rinfo.height))

        self._add_fb(builder, imp_rect)
        if mos_type.is_substrate and mos_type is not row_type.sub_type:
            row_type = mos_type
        for lay_purp in self._thres_imp_well_layers_iter(
                row_type, mos_type, rinfo.threshold):
            builder.add_rect_arr(lay_purp, imp_rect)

        return builder.get_info(blk_rect)
Esempio n. 25
0
    def set_mos_size(self, num_cols: int = 0, num_tiles: int = 0) -> None:
        if not self.size_defined:
            ainfo = self._arr_info
            used_arr = self._used_arr

            if num_cols > 0:
                used_arr.num_cols = num_cols
            if num_tiles > 0:
                used_arr.set_num_tiles(num_tiles)

            width = used_arr.num_cols * ainfo.sd_pitch
            height = used_arr.height
            self.set_size_from_bound_box(ainfo.top_layer, BBox(0, 0, width, height))
        else:
            raise ValueError('Cannot change tile_size once it is set.')
Esempio n. 26
0
def test_physical_valid(xl, yl, xh, yh, physical, valid):
    ans = BBox(xl, yl, xh, yh)
    assert ans.is_physical() == physical
    assert ans.is_valid() == valid

    # check orientation based constructor works
    b1 = BBox(Orient2D.x, xl, xh, yl, yh)
    b2 = BBox(Orient2D.y, yl, yh, xl, xh)
    assert b1 == ans
    assert b2 == ans
Esempio n. 27
0
def test_empty():
    rtree = RTree()

    assert not rtree
    assert not rtree.bound_box.is_valid()

    with pytest.raises(IndexError):
        # noinspection PyStatementEffect
        rtree[0]

    with pytest.raises(IndexError):
        rtree.pop(0)

    objects = [obj for obj in rtree]
    assert not objects
    objects = [obj for obj in rtree.intersect_iter(BBox(0, 0, 1, 1))]
    assert not objects
Esempio n. 28
0
    def draw_layout(self):
        w: int = self.params['w']
        h: int = self.params['h']
        fill_layer: int = self.params['fill_layer']

        grid = self.grid
        tech_info = grid.tech_info
        fill_info = tech_info.get_max_space_fill_info(fill_layer)

        self.set_size_from_bound_box(fill_layer,
                                     BBox(0, 0, w, h),
                                     round_up=True)
        bbox = self.bound_box

        tdir = grid.get_direction(fill_layer)
        pdir = tdir.perpendicular()
        margin = fill_info.get_margin(pdir)
        margin_le = fill_info.get_margin(tdir)
        sp_le = fill_info.get_space(tdir)
        dim = bbox.get_dim(pdir)
        dim_le = bbox.get_dim(tdir)

        tidxl = grid.coord_to_track(fill_layer, margin, mode=RoundMode.LESS_EQ)
        tidxr = grid.coord_to_track(fill_layer,
                                    dim - margin,
                                    mode=RoundMode.GREATER_EQ)
        wlen = grid.get_min_cont_length(fill_layer, 1)

        # fill inner
        self.add_wires(fill_layer,
                       tidxl + 1,
                       margin_le,
                       dim_le - margin_le,
                       num=tidxr - tidxl - 1)

        lower = margin_le
        self.add_wires(fill_layer, tidxl, lower, lower + wlen)
        lower += wlen + sp_le
        self.add_wires(fill_layer, tidxl, lower, lower + wlen)
        lower += wlen + sp_le + 2
        self.add_wires(fill_layer, tidxl, lower, lower + wlen)
        lower += wlen + 2 * sp_le + wlen * 2
        self.add_wires(fill_layer, tidxl, lower, lower + wlen)

        self.do_max_space_fill(fill_layer, bbox)
Esempio n. 29
0
    def get_blk_info(self, conn_layer: int, w: int, h: int, nx: int, ny: int,
                     **kwargs: Any) -> Optional[ArrayLayInfo]:
        res_type: str = kwargs.get('res_type', 'standard')

        if res_type != 'metal':
            raise ValueError(f'unsupported resistor type: {res_type}')

        x_pitch: int = self.res_config['x_pitch']
        conn_w: int = self.res_config['conn_w']

        sp_le = self.tech_info.get_min_line_end_space('M1CA',
                                                      conn_w,
                                                      purpose='drawing',
                                                      even=True)

        builder = LayoutInfoBuilder()
        x0 = x_pitch // 2
        yl = sp_le
        yh = h - sp_le
        x1 = w - x_pitch // 2
        boxl = BBox(x0 - conn_w // 2, yl, x0 + conn_w // 2, yh)
        builder.add_rect_arr(('M1CA', 'drawing'), boxl, nx=2, spx=x1 - x0)
        xm = w // 2
        boxm = BBox(xm - conn_w // 2, yl, xm + conn_w // 2, yh)
        builder.add_rect_arr(('M1CA', 'drawing'), boxm)
        boxr = BBox(boxm.xl, yl + conn_w, boxm.xh, yh - conn_w)
        builder.add_rect_arr(('m1res', 'drawing'), boxr)
        builder.add_rect_arr(('M1CA', 'drawing'),
                             BBox(boxl.xl, yl, boxm.xh, yl + conn_w))
        boxr = boxl.get_move_by(dx=x1 - x0)
        builder.add_rect_arr(('M1CA', 'drawing'),
                             BBox(boxm.xl, yh - conn_w, boxr.xh, yh))

        tidu = HalfInt(2 * ((w // x_pitch) - 1))
        return ArrayLayInfo(
            builder.get_info(BBox(0, 0, w, h)),
            ImmutableSortedDict({
                'u':
                WireArrayInfo(1, tidu, yl, yh, 1, 1, 0),
                'l':
                WireArrayInfo(1, HalfInt(0), yl, yh, 1, 1, 0)
            }), ImmutableSortedDict(), ImmutableSortedDict())
Esempio n. 30
0
    def draw_boundaries(self,
                        master: MOSBase,
                        top_layer: int,
                        *,
                        half_blk_x: bool = True,
                        half_blk_y: bool = True) -> PyLayInstance:
        self._core = master

        tech_cls = master.tech_cls
        bbox = master.bound_box
        used_arr = master.used_array

        w_blk, h_blk = self.grid.get_block_size(top_layer,
                                                half_blk_x=half_blk_x,
                                                half_blk_y=half_blk_y)

        w_master = bbox.w
        h_master = bbox.h
        w_edge = tech_cls.get_edge_width(w_master, w_blk)
        base_end_info = tech_cls.get_mos_base_end_info(master.place_info,
                                                       h_blk)

        # get top/bottom boundary delta/height
        num_tiles = used_arr.num_tiles
        idx_bot = int(used_arr.get_flip_tile(0))
        idx_top = int(not used_arr.get_flip_tile(num_tiles - 1))
        dy_bot = base_end_info.h_blk[idx_bot]
        dy_top = base_end_info.h_blk[idx_top]
        h_end_bot = base_end_info.h_mos_end[idx_bot]
        h_end_top = base_end_info.h_mos_end[idx_top]

        self._xform = Transform(w_edge, dy_bot)
        inst = self.add_instance(master, inst_name='X0', xform=self._xform)

        my_used_arr = used_arr.get_copy()
        sd_pitch = tech_cls.sd_pitch
        w_tot = w_edge * 2 + w_master
        h_tot = dy_bot + dy_top + h_master
        self._fill_space(master.grid, tech_cls, w_edge, my_used_arr, sd_pitch,
                         w_tot, h_tot, dy_bot, h_end_bot, h_end_top)

        self.set_size_from_bound_box(top_layer, BBox(0, 0, w_tot, h_tot))
        return inst