Esempio n. 1
0
    def draw_dum_connection_helper(
            self,
            template,  # type: TemplateBase
            lch_unit,  # type: int
            fg,  # type: int
            sd_pitch,  # type: int
            xc,  # type: int
            od_y,  # type: Tuple[int, int]
            md_y,  # type: Tuple[int, int]
            ds_x_list,  # type: List[int]
            gate_tracks,  # type: List[Union[float, int]]
            left_edge,  # type: bool
            right_edge,  # type: bool
            options,  # type: Dict[str, Any]
    ):
        # type: (...) -> List[WireArray]

        res = self.res
        lay_name_table = self.config['layer_name']

        mos_constants = self.get_mos_tech_constants(lch_unit)
        g_m1_dum_h = mos_constants['g_m1_dum_h']

        conn_yloc_info = self.get_conn_yloc_info(lch_unit, od_y, md_y, False)

        m1_lay = lay_name_table[1]
        m1_yb = conn_yloc_info['g_y_list'][0][0]
        m1_yt = conn_yloc_info['d_y_list'][0][1]

        # draw gate/drain/source connection to M1
        self.draw_g_connection(template,
                               lch_unit,
                               fg,
                               sd_pitch,
                               xc,
                               od_y,
                               md_y, [],
                               is_sub=False,
                               is_dum=True)
        self.draw_ds_connection(template,
                                lch_unit,
                                fg,
                                sd_pitch,
                                xc,
                                od_y,
                                md_y, [], [],
                                False,
                                1,
                                1,
                                is_dum=True)
        self.draw_ds_connection(template,
                                lch_unit,
                                fg,
                                sd_pitch,
                                xc,
                                od_y,
                                md_y, [], [],
                                True,
                                1,
                                2,
                                is_dum=True)

        # short M1 together
        dum_layer = self.get_dum_conn_layer()
        for wire_xc in ds_x_list:
            tidx = template.grid.coord_to_track(dum_layer,
                                                wire_xc,
                                                unit_mode=True)
            template.add_wires(dum_layer, tidx, m1_yb, m1_yt, unit_mode=True)
        xl = ds_x_list[0]
        xr = ds_x_list[-1]
        if xr > xl:
            template.add_rect(
                m1_lay,
                BBox(xl, m1_yb, xr, m1_yb + g_m1_dum_h, res, unit_mode=True))

        # return gate ports
        return [
            WireArray(TrackID(dum_layer, tidx), m1_yb * res, m1_yt * res, res)
            for tidx in gate_tracks
        ]
Esempio n. 2
0
    def draw_ds_connection(
            self,  # type: MOSTechCDSFFMPT
            template,  # type: TemplateBase
            lch_unit,  # type: int
            fg,  # type: int
            wire_pitch,  # type: int
            xc,  # type: int
            od_y,  # type: Tuple[int, int]
            md_y,  # type: Tuple[int, int]
            dum_x_list,  # type: List[int]
            conn_x_list,  # type: List[int]
            align_gate,  # type: bool
            wire_dir,  # type: int
            ds_code,  # type: int
            **kwargs):
        # type: (...) -> Tuple[List[WireArray], List[WireArray]]

        is_dum = kwargs.get('is_dum', False)

        res = self.res
        mos_lay_table = self.config['mos_layer_table']

        mos_constants = self.get_mos_tech_constants(lch_unit)
        md_w = mos_constants['md_w']
        bot_layer = mos_constants['d_bot_layer']
        via_info = mos_constants['d_via']

        is_sub = (ds_code == 3)
        conn_yloc_info = self.get_conn_yloc_info(lch_unit, od_y, md_y, is_sub)
        conn_drc_info = self.get_conn_drc_info(lch_unit, 'd')

        dum_layer = self.get_dum_conn_layer()
        mos_layer = self.get_mos_conn_layer()
        dum_warrs, conn_warrs = [], []

        # figure out via X coordinates
        if is_sub:
            via_x_list = list(range(xc, xc + (fg + 1) * wire_pitch,
                                    wire_pitch))
            conn_y_list = conn_yloc_info['d_y_list']
        else:
            if ds_code == 1:
                via_x_list = list(
                    range(xc, xc + (fg + 1) * wire_pitch, 2 * wire_pitch))
            else:
                via_x_list = list(
                    range(xc + wire_pitch, xc + (fg + 1) * wire_pitch,
                          2 * wire_pitch))
            if align_gate:
                conn_y_list = conn_yloc_info['d_y_list']
            else:
                conn_y_list = conn_yloc_info['s_y_list']

        # connect from OD up to M3
        stop_layer = dum_layer if is_dum else mos_layer
        lay_list = range(bot_layer, stop_layer + 1)
        prev_info = md_y[0], md_y[1], 'y', md_w, mos_lay_table['MD']
        for cur_lay, cur_y, via_dim, via_sp, via_ble, via_tle in \
                zip(lay_list, conn_y_list, via_info['dim'], via_info['sp'],
                    via_info['bot_enc_le'], via_info['top_enc_le']):
            prev_info = self.up_one_layer(template, cur_lay, cur_y, via_dim,
                                          via_sp, via_ble, via_tle, via_x_list,
                                          prev_info, conn_drc_info)

        # add WireArrays
        if stop_layer >= dum_layer:
            cur_yb, cur_yt = conn_y_list[dum_layer - bot_layer]
            for conn_xc in dum_x_list:
                tidx = template.grid.coord_to_track(dum_layer,
                                                    conn_xc,
                                                    unit_mode=True)
                dum_warrs.append(
                    WireArray(TrackID(dum_layer, tidx), cur_yb * res,
                              cur_yt * res, res))
        if stop_layer >= mos_layer:
            cur_yb, cur_yt = conn_y_list[mos_layer - bot_layer]
            for conn_xc in conn_x_list:
                tidx = template.grid.coord_to_track(mos_layer,
                                                    conn_xc,
                                                    unit_mode=True)
                conn_warrs.append(
                    WireArray(TrackID(mos_layer, tidx), cur_yb * res,
                              cur_yt * res, res))

        return dum_warrs, conn_warrs
Esempio n. 3
0
    def draw_g_connection(
            self,  # type: MOSTechCDSFFMPT
            template,  # type: TemplateBase
            lch_unit,  # type: int
            fg,  # type: int
            sd_pitch,  # type: int
            xc,  # type: int
            od_y,  # type: Tuple[int, int]
            md_y,  # type: Tuple[int, int]
            conn_x_list,  # type: List[int]
            is_sub=False,  # type: bool
            **kwargs):
        # type: (...) -> List[WireArray]

        is_dum = kwargs.get('is_dum', False)
        res = self.res
        mos_lay_table = self.config['mos_layer_table']
        lay_name_table = self.config['layer_name']
        via_id_table = self.config['via_id']

        mos_constants = self.get_mos_tech_constants(lch_unit)
        mp_po_ovl_constants = mos_constants['mp_po_ovl_constants']
        mp_po_ovl_constants_sub = mos_constants['mp_po_ovl_constants_sub']
        mp_h = mos_constants['mp_h']
        mp_h_sub = mos_constants['mp_h_sub']
        via_info = mos_constants['g_via']

        conn_yloc_info = self.get_conn_yloc_info(lch_unit, od_y, md_y, is_sub)
        conn_drc_info = self.get_conn_drc_info(lch_unit, 'g')

        conn_warrs = []

        mp_lay = mos_lay_table['MP']
        m1_w = conn_drc_info[1]['w']
        mp_y_list = conn_yloc_info['mp_y_list']
        v0_id = via_id_table[(mos_lay_table['MP'], lay_name_table[1])]
        if is_sub:
            mp_po_ovl = mp_po_ovl_constants_sub[
                0] + lch_unit * mp_po_ovl_constants_sub[1]
            # connect gate to M1 only
            m1_yb, m1_yt = conn_yloc_info['d_y_list'][0]
            via_w, via_h = via_info['dim'][0]
            bot_encx = via_info['bot_enc_le'][0]
            top_encx = (m1_w - via_w) // 2
            bot_ency = (mp_h_sub - via_h) // 2
            top_ency = via_info['top_enc_le'][0]

            mp_dx = sd_pitch // 2 - lch_unit // 2 + mp_po_ovl
            enc1 = [bot_encx, bot_encx, bot_ency, bot_ency]
            enc2 = [top_encx, top_encx, top_ency, top_ency]
            for via_xc in range(xc, xc + (fg + 1) * sd_pitch, 2 * sd_pitch):
                mp_xl = via_xc - mp_dx
                mp_xr = via_xc + mp_dx
                for mp_yb, mp_yt in mp_y_list:
                    template.add_rect(
                        mp_lay,
                        BBox(mp_xl, mp_yb, mp_xr, mp_yt, res, unit_mode=True))
                    mp_yc = (mp_yb + mp_yt) // 2
                    template.add_via_primitive(v0_id, [via_xc, mp_yc],
                                               enc1=enc1,
                                               enc2=enc2,
                                               cut_width=via_w,
                                               cut_height=via_h,
                                               unit_mode=True)
                template.add_rect(
                    'M1',
                    BBox(via_xc - m1_w // 2,
                         m1_yb,
                         via_xc + m1_w // 2,
                         m1_yt,
                         res,
                         unit_mode=True))
        else:
            mp_po_ovl = mp_po_ovl_constants[
                0] + lch_unit * mp_po_ovl_constants[1]

            if fg % 2 == 0:
                gate_fg_list = [2] * (fg // 2)
            else:
                if fg == 1:
                    raise ValueError('cannot connect 1 finger transistor')
                if fg <= 5:
                    gate_fg_list = [fg]
                else:
                    num_mp_half = (fg - 3) // 2
                    gate_fg_list = list(
                        chain(repeat(2, num_mp_half), [3],
                              repeat(2, num_mp_half)))

            # connect gate to M1.
            tot_fg = 0
            mp_yb, mp_yt = mp_y_list[0]
            m1_yb, m1_yt = conn_yloc_info['g_y_list'][0]
            via_w, via_h = via_info['dim'][0]
            bot_encx = via_info['bot_enc_le'][0]
            top_encx = (m1_w - via_w) // 2
            bot_ency = (mp_h - via_h) // 2
            top_ency = via_info['top_enc_le'][0]
            enc1 = [bot_encx, bot_encx, bot_ency, bot_ency]
            enc2 = [top_encx, top_encx, top_ency, top_ency]
            via_yc = (mp_yb + mp_yt) // 2
            via_x_list = []
            for num_fg in gate_fg_list:
                via_xoff = xc + (tot_fg + 1) * sd_pitch
                cur_xc = xc + tot_fg * sd_pitch + num_fg * sd_pitch // 2
                # draw MP
                mp_w = (num_fg - 1) * sd_pitch - lch_unit + 2 * mp_po_ovl
                mp_xl = cur_xc - mp_w // 2
                mp_xr = mp_xl + mp_w
                template.add_rect(
                    mp_lay,
                    BBox(mp_xl, mp_yb, mp_xr, mp_yt, res, unit_mode=True))
                # draw V0, M1
                for via_xc in range(via_xoff,
                                    via_xoff + (num_fg - 1) * sd_pitch,
                                    sd_pitch):
                    cur_tidx = template.grid.coord_to_track(1,
                                                            via_xc,
                                                            unit_mode=True)
                    template.add_via_primitive(v0_id, [via_xc, via_yc],
                                               enc1=enc1,
                                               enc2=enc2,
                                               cut_width=via_w,
                                               cut_height=via_h,
                                               unit_mode=True)
                    template.add_wires(1,
                                       cur_tidx,
                                       m1_yb,
                                       m1_yt,
                                       unit_mode=True)
                    via_x_list.append(via_xc)
                tot_fg += num_fg

            # connect from M1 up to M3 if not dummy gate connection
            if not is_dum:
                conn_y_list = conn_yloc_info['g_y_list'][1:]
                lay_list = range(2, 2 + len(conn_y_list))
                prev_info = m1_yb, m1_yt, 'y', m1_w, lay_name_table[1]
                for cur_lay, cur_y, via_dim, via_sp, via_ble, via_tle in \
                        zip(lay_list, conn_y_list, via_info['dim'][1:], via_info['sp'][1:],
                            via_info['bot_enc_le'][1:], via_info['top_enc_le'][1:]):
                    prev_info = self.up_one_layer(template, cur_lay, cur_y,
                                                  via_dim, via_sp, via_ble,
                                                  via_tle, via_x_list,
                                                  prev_info, conn_drc_info)
                    via_x_list = conn_x_list

                # add ports
                mos_layer = self.get_mos_conn_layer()
                cur_yb, cur_yt = conn_y_list[-1]
                for conn_xc in conn_x_list:
                    tidx = template.grid.coord_to_track(mos_layer,
                                                        conn_xc,
                                                        unit_mode=True)
                    conn_warrs.append(
                        WireArray(TrackID(mos_layer, tidx), cur_yb * res,
                                  cur_yt * res, res))

        return conn_warrs
Esempio n. 4
0
    def _draw_layout_helper(self, io_names, sup_name, reserve_tracks,
                            bus_layer, bus_margin, show_pins, track_width):
        # compute bus length
        track_space = self.grid.get_num_space_tracks(bus_layer,
                                                     width_ntr=track_width)
        io_names = {name: idx for idx, name in enumerate(io_names)}
        bus_lower = None
        bus_upper = None
        reserve_list = []
        io_dict = {bus_layer - 1: [], bus_layer + 1: []}
        for name, layer, track, width in reserve_tracks:
            if layer == bus_layer - 1 or layer == bus_layer + 1:
                reserve_list.append((layer, track, width))
                num_space = self.grid.get_num_space_tracks(layer,
                                                           width_ntr=width)
                lower = self.grid.get_wire_bounds(layer,
                                                  track - num_space,
                                                  width=width,
                                                  unit_mode=True)[0]
                upper = self.grid.get_wire_bounds(layer,
                                                  track + num_space,
                                                  width=width,
                                                  unit_mode=True)[1]
                if bus_lower is None:
                    bus_lower, bus_upper = lower, upper
                else:
                    bus_lower = min(bus_lower, lower)
                    bus_upper = max(bus_upper, upper)

                idx = io_names.get(name, -1)
                if idx >= 0:
                    io_dict[layer].append((name, idx, track, width))

        bus_upper = self._get_bound(bus_upper, bus_layer, 1)
        # draw input buses
        track_pitch = track_width + track_space
        track0 = bus_margin + track_space + (track_width + 1) / 2
        wire_layers = (bus_layer - 1, bus_layer + 1)
        for lay in wire_layers:
            for name, idx, track, width in io_dict[lay]:
                mid = self.grid.track_to_coord(lay, track, unit_mode=True)
                cur_tr_idx = track0 + idx * track_pitch
                w = self.add_wires(bus_layer,
                                   cur_tr_idx,
                                   0,
                                   mid,
                                   width=track_width,
                                   unit_mode=True)
                w_in = self.connect_to_tracks(w,
                                              TrackID(lay, track, width=width),
                                              min_len_mode=0)
                pin_w = WireArray(
                    TrackID(bus_layer, cur_tr_idx, width=track_width), 0,
                    self.grid.get_min_length(bus_layer, 1))
                self.add_pin(name, pin_w, show=show_pins)
                self.add_pin(name + '_in', w_in, show=show_pins)

        # compute size
        last_sup_track = track0 + (len(io_names) - 1) * track_pitch + (
            track_width + 1) / 2 + track_space
        bus_wl = self.grid.get_wire_bounds(bus_layer,
                                           bus_margin,
                                           unit_mode=True)[0]
        bus_wu = self.grid.get_wire_bounds(bus_layer,
                                           last_sup_track,
                                           unit_mode=True)[1]
        size_wu = self.grid.get_wire_bounds(bus_layer,
                                            last_sup_track + bus_margin,
                                            unit_mode=True)[1]
        if self.grid.get_direction(bus_layer) == 'x':
            cur_width, cur_height = bus_upper, size_wu
        else:
            cur_width, cur_height = size_wu, bus_upper
        self.size = self.grid.get_size_tuple(bus_layer + 2,
                                             cur_width,
                                             cur_height,
                                             round_up=True,
                                             unit_mode=True)
        self.array_box = self.bound_box

        # reserve tracks
        for lay, track, width in reserve_list:
            self.reserve_tracks(lay, track, width)

        # draw supply wires
        sup_warr_list = None
        sup_pitch = last_sup_track - bus_margin
        for lay in wire_layers:
            tr_max = self.grid.find_next_track(lay,
                                               bus_upper,
                                               mode=1,
                                               unit_mode=True)
            tr_idx_list = list(range(1, tr_max + 1, 2))
            avail_list = self.get_available_tracks(lay,
                                                   tr_idx_list,
                                                   bus_wl,
                                                   bus_wu,
                                                   unit_mode=True)
            # connect
            sup_warr_list = []
            for aidx in avail_list:
                sup_warr_list.append(
                    self.add_wires(lay, aidx, bus_wl, bus_wu, unit_mode=True))
            self.connect_to_tracks(sup_warr_list,
                                   TrackID(bus_layer,
                                           bus_margin,
                                           width=1,
                                           num=2,
                                           pitch=sup_pitch),
                                   track_lower=0)

        num_sup_tracks = self.grid.get_num_tracks(self.size, bus_layer + 2)
        num_top_sup = 1
        sup_w = self.grid.get_max_track_width(bus_layer + 2, num_top_sup,
                                              num_sup_tracks)
        # TODO: find best way to do this in process independent way
        while sup_w > 10:
            num_top_sup += 1
            sup_w = self.grid.get_max_track_width(bus_layer + 2, num_top_sup,
                                                  num_sup_tracks)
        sup_tr_list = self.grid.get_evenly_spaced_tracks(
            num_top_sup, num_sup_tracks, sup_w)
        for sup_idx in sup_tr_list:
            sup_warr = self.connect_to_tracks(
                sup_warr_list, TrackID(bus_layer + 2, sup_idx, width=sup_w))
            self.add_pin(sup_name, sup_warr, show=show_pins)
Esempio n. 5
0
 def _get_wire_array(self, layer_id, tr0, num, lower, upper, pitch=1):
     res = self.config['resolution']
     tid = TrackID(layer_id, tr0, num=num, pitch=pitch)
     return WireArray(tid, lower, upper, res=res, unit_mode=True)
Esempio n. 6
0
    def draw_dum_connection(self, template, mos_info, edge_mode, gate_tracks,
                            options):
        # type: (TemplateBase, Dict[str, Any], int, List[int], Dict[str, Any]) -> None

        res = self.config['resolution']
        mos_lay_table = self.config['mos_layer_table']
        lay_name_table = self.config['layer_name']

        layout_info = mos_info['layout_info']
        sd_yc = mos_info['sd_yc']

        lch_unit = layout_info['lch_unit']
        sd_pitch = layout_info['sd_pitch']
        fg = layout_info['fg']
        b_po_y_list = layout_info['b_po_y_list']
        g_y_list = layout_info['g_y_list']
        d_y_list = layout_info['d_y_list']
        b_y_list = layout_info['b_y_list']

        mos_constants = self.get_mos_tech_constants(lch_unit)
        sp_gb_po = mos_constants['sp_gb_po']
        po_od_spx = mos_constants['po_od_spx']
        w_delta = mos_constants['w_delta']

        sd_pitch2 = sd_pitch // 2
        width = fg * sd_pitch
        lch2 = lch_unit // 2
        po_name = mos_lay_table['PO_dummy']
        od_name = mos_lay_table['OD_dummy']
        po_yb = g_y_list[0][0] - sd_yc
        po_yt = b_po_y_list[0][0] - sp_gb_po - sd_yc
        od_yb = d_y_list[0][0] - sd_yc
        od_yt = d_y_list[0][1] + w_delta - sd_yc
        od_w = sd_pitch - lch_unit - 2 * po_od_spx

        if (edge_mode & 1) == 0:
            po_box = BBox(sd_pitch2 - lch2,
                          po_yb,
                          sd_pitch2 + lch2,
                          po_yt,
                          res,
                          unit_mode=True)
            template.add_rect(po_name, po_box, unit_mode=True)
            po_xcl = sd_pitch2 * 3
        else:
            po_xcl = sd_pitch2
        od_xl = sd_pitch2 + lch2 + po_od_spx
        od_xr = od_xl + od_w

        if (edge_mode & 2) == 0:
            po_box = BBox(width - sd_pitch2 - lch2,
                          po_yb,
                          width - sd_pitch2 + lch2,
                          po_yt,
                          res,
                          unit_mode=True)
            template.add_rect(po_name, po_box, unit_mode=True)
            po_xcr = width - sd_pitch2 * 3
        else:
            po_xcr = width - sd_pitch2

        # get dummy PO X coordinates
        nx = (po_xcr - po_xcl) // sd_pitch + 1
        po_yt = b_po_y_list[0][1] - sd_yc
        if nx > 0:
            # draw dummy PO
            po_box = BBox(po_xcl - lch2,
                          po_yb,
                          po_xcl + lch2,
                          po_yt,
                          res,
                          unit_mode=True)
            template.add_rect(po_name,
                              po_box,
                              nx=nx,
                              spx=sd_pitch,
                              unit_mode=True)
        if fg > 1:
            od_box = BBox(od_xl, od_yb, od_xr, od_yt, res, unit_mode=True)
            template.add_rect(od_name,
                              od_box,
                              nx=fg - 1,
                              spx=sd_pitch,
                              unit_mode=True)

        # draw body M1
        m1_name = lay_name_table[1]
        m1_yb, m1_yt = b_y_list[1]
        m1_box = BBox(0, m1_yb, width, m1_yt, res, unit_mode=True)
        m1_box = m1_box.move_by(dy=-sd_yc, unit_mode=True)
        template.add_rect(m1_name, m1_box)

        # add body ports
        dum_layer = self.get_dum_conn_layer()
        for tidx in gate_tracks:
            warr = WireArray(TrackID(dum_layer, tidx),
                             m1_box.bottom_unit,
                             m1_box.top_unit,
                             res=res,
                             unit_mode=True)
            template.add_pin('dummy', warr, show=False)
Esempio n. 7
0
    def draw_res_core(self, template, layout_info):
        # type: (TemplateBase, Dict[str, Any]) -> None

        mos_lay_table = self.config['mos_layer_table']
        res_lay_table = self.config['res_layer_table']

        fin_h2 = self.mos_tech.mos_config['fin_h'] // 2
        fin_p2 = self.mos_tech.mos_config['mos_pitch'] // 2

        grid = template.grid
        res = grid.resolution

        finfet_lay = mos_lay_table['FB']
        rpdmy_lay = res_lay_table['RPDMY']
        res_lay = res_lay_table['RES']

        w = layout_info['w']
        l = layout_info['l']
        threshold = layout_info['threshold']
        res_type = layout_info['res_type']
        sub_type = layout_info['sub_type']
        wcore = layout_info['w_core']
        hcore = layout_info['h_core']
        track_widths = layout_info['track_widths']

        core_info = layout_info['core_info']
        lr_od_loc = core_info['lr_od_loc']
        top_od_loc = core_info['top_od_loc']
        bot_od_loc = core_info['bot_od_loc']
        lr_fg = core_info['lr_fg']
        tb_fg = core_info['tb_fg']
        port_info = core_info['port_info']
        fill_info = core_info['fill_info']

        xc, yc = wcore // 2, hcore // 2
        wres, lres, _, _ = self.get_res_dimension(l, w)

        # set size and draw implant layers
        implant_layers = self.get_res_imp_layers(res_type, sub_type, threshold)
        arr_box = BBox(0, 0, wcore, hcore, res, unit_mode=True)
        # mos layer need to be snap to fin edges.
        fin_box = BBox(0,
                       -fin_p2 - fin_h2,
                       wcore,
                       hcore + fin_p2 + fin_h2,
                       res,
                       unit_mode=True)
        for lay in implant_layers:
            if lay == finfet_lay:
                template.add_rect(lay, fin_box)
            else:
                template.add_rect(lay, arr_box)
        template.array_box = arr_box
        template.prim_bound_box = arr_box
        template.add_cell_boundary(arr_box)

        # draw RPDMY
        rpdmy_yb = yc - l // 2
        rpdmy_yt = rpdmy_yb + l
        template.add_rect(
            rpdmy_lay, BBox(0, rpdmy_yb, wcore, rpdmy_yt, res, unit_mode=True))

        # draw resistor
        rh_yb = yc - lres // 2
        rh_xl = xc - wres // 2
        template.add_rect(
            res_lay,
            BBox(rh_xl, rh_yb, rh_xl + wres, rh_yb + lres, res,
                 unit_mode=True))

        # draw vias and ports
        bot_layer = self.get_bot_layer()
        for port_name, rect_list, via_list in port_info:
            for rect_info in rect_list:
                template.add_rect(rect_info['layer'], rect_info['bbox'])
            for via_params in via_list:
                template.add_via_primitive(**via_params)

            tr_bbox = rect_list[-1]['bbox']
            port_tr = grid.coord_to_track(bot_layer,
                                          tr_bbox.yc_unit,
                                          unit_mode=True)
            pin_warr = WireArray(TrackID(bot_layer,
                                         port_tr,
                                         width=track_widths[0]),
                                 tr_bbox.left_unit,
                                 tr_bbox.right_unit,
                                 res=res,
                                 unit_mode=True)
            template.add_pin(port_name, pin_warr, show=False)

        # draw dummies
        self._draw_dummies(template, 0, lr_fg, lr_od_loc)
        self._draw_dummies(template, wcore, lr_fg, lr_od_loc)
        self._draw_dummies(template, xc, tb_fg, top_od_loc)
        self._draw_dummies(template, xc, tb_fg, bot_od_loc)

        # draw metal fill
        for layer, exc_layer, _, _, core_x, core_y, _, _, _, _ in fill_info:
            template.add_rect(exc_layer, arr_box)
            for xl, xr in core_x:
                for yb, yt in core_y:
                    template.add_rect(
                        layer, BBox(xl, yb, xr, yt, res, unit_mode=True))
Esempio n. 8
0
    def draw_res_core(self, template, layout_info):
        # type: (TemplateBase, Dict[str, Any]) -> None

        mos_layer_table = self.config['mos_layer_table']
        res_layer_table = self.config['res_layer_table']
        metal_exclude_table = self.config['metal_exclude_table']
        layer_table = self.config['layer_name']
        res_info = self.res_config['info']
        imp_ency = self.res_config['imp_enc'][1]

        grid = template.grid
        res = grid.resolution

        w = layout_info['w']
        l = layout_info['l']
        res_type = layout_info['res_type']
        sub_type = layout_info['sub_type']
        threshold = layout_info['threshold']
        wcore = layout_info['w_core']
        hcore = layout_info['h_core']
        track_widths = layout_info['track_widths']

        core_info = layout_info['core_info']
        lr_od_xloc = core_info['lr_od_xloc']
        top_od_yloc = core_info['top_od_yloc']
        bot_od_yloc = core_info['bot_od_yloc']
        tb_od_xloc = core_info['tb_od_xloc']
        port_info = core_info['port_info']

        res_info = res_info[res_type]
        need_rpo = res_info['need_rpo']
        need_rpdmy = res_info['need_rpdmy']
        od_in_res = res_info['od_in_res']

        xc, yc = wcore // 2, hcore // 2
        wres, lres, _, _ = self.get_res_dimension(l, w)

        # set size and draw implant layers
        implant_layers = self.get_res_imp_layers(res_type, sub_type, threshold)
        arr_box = BBox(0, 0, wcore, hcore, res, unit_mode=True)
        po_yb = yc - lres // 2
        po_yt = yc + lres // 2
        if od_in_res:
            imp_box = arr_box
        else:
            imp_box = BBox(0,
                           po_yb - imp_ency,
                           wcore,
                           po_yt + imp_ency,
                           res,
                           unit_mode=True)
        for lay in implant_layers:
            template.add_rect(lay, imp_box)
        template.array_box = arr_box
        template.prim_bound_box = arr_box

        # draw RPDMY
        po_xl = xc - wres // 2
        po_xr = xc + wres // 2
        rpdmy_yb = yc - l // 2
        rpdmy_yt = rpdmy_yb + l
        if need_rpdmy:
            rpdmy_name = res_layer_table['RPDMY']
            template.add_rect(
                rpdmy_name,
                BBox(po_xl, rpdmy_yb, po_xr, rpdmy_yt, res, unit_mode=True))
        if need_rpo:
            # draw RPO
            rpo_name = res_layer_table['RPO']
            template.add_rect(
                rpo_name,
                BBox(0, rpdmy_yb, wcore, rpdmy_yt, res, unit_mode=True))

        # draw PO
        po_name = mos_layer_table['PO']
        template.add_rect(
            po_name, BBox(po_xl, po_yb, po_xr, po_yt, res, unit_mode=True))

        # draw vias and ports
        m1_name = layer_table[1]
        bot_layer = self.get_bot_layer()
        for port_name, v0_params, v1_params, m1_box, m2_box in port_info:
            template.add_rect(m1_name, m1_box)
            template.add_via_primitive(**v0_params)
            template.add_via_primitive(**v1_params)
            m2_tr = grid.coord_to_track(bot_layer,
                                        m2_box.yc_unit,
                                        unit_mode=True)
            pin_warr = WireArray(TrackID(bot_layer,
                                         m2_tr,
                                         width=track_widths[0]),
                                 m2_box.left_unit,
                                 m2_box.right_unit,
                                 res=res,
                                 unit_mode=True)
            template.add_pin(port_name, pin_warr, show=False)

        # draw dummies
        po_y_list = [(po_yb, po_yt)]
        self._draw_dummies(template, lr_od_xloc, po_y_list)
        self._draw_dummies(template, lr_od_xloc, po_y_list, dx=wcore)
        self._draw_dummies(template, tb_od_xloc, bot_od_yloc)
        self._draw_dummies(template, tb_od_xloc, top_od_yloc)

        # draw M1 exclusion layer
        m1_exc_layer = metal_exclude_table[1]
        template.add_rect(m1_exc_layer, arr_box)

        # draw M1 fill
        m1_x_list = core_info['m1_core_x']
        m1_y_list = core_info['m1_core_y']
        for xl, xr in m1_x_list:
            for yb, yt in m1_y_list:
                template.add_rect(m1_name,
                                  BBox(xl, yb, xr, yt, res, unit_mode=True))