def generate_clkgcalbuf_wbnd(laygen, objectname_pfix, workinglib, clkgcalbuf_name, placement_grid, origin=np.array([0, 0])):
    clkgcalbuf_origin = origin + laygen.get_template_size('boundary_bottomleft', pg)
    iclkgcalbuf=laygen.place(name="I" + objectname_pfix + 'SP0', templatename=clkgcalbuf_name,
                         gridname=pg, xy=clkgcalbuf_origin, template_libname=workinglib)
    xy0=laygen.get_template_size(name=clkgcalbuf_name, gridname=pg, libname=workinglib)
    xsp=xy0[0]
    #ysp=xy0[1]
    m_bnd = int(xsp / laygen.get_template_size('boundary_bottom', gridname=pg)[0])
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=['nmos4_fast_left', 'pmos4_fast_left'],
                            transform_left=['R0', 'MX'],
                            devname_right=['nmos4_fast_right', 'pmos4_fast_right'],
                            transform_right=['R0', 'MX'],
                            origin=origin)
    #pins
    clkgcalbuf_template = laygen.templates.get_template(clkgcalbuf_name, workinglib)
    clkgcalbuf_pins=clkgcalbuf_template.pins
    clkgcalbuf_origin_phy = laygen.get_inst_bbox(iclkgcalbuf.name)[0]
    vddcnt=0
    vsscnt=0
    for pn, p in clkgcalbuf_pins.items():
        if pn.startswith('VDD'):
            laygen.add_pin('VDD' + str(vddcnt), 'VDD', clkgcalbuf_origin_phy+p['xy'], p['layer'])
            vddcnt += 1
        if pn.startswith('VSS'):
            laygen.add_pin('VSS' + str(vsscnt), 'VSS', clkgcalbuf_origin_phy+p['xy'], p['layer'])
            vsscnt += 1
        else:
            laygen.add_pin(pn, p['netname'], clkgcalbuf_origin_phy+p['xy'], p['layer'])
Example #2
0
def generate_space_wbnd(laygen,
                        objectname_pfix,
                        workinglib,
                        space_name,
                        placement_grid,
                        origin=np.array([0, 0])):
    space_origin = origin + laygen.get_xy(
        obj=laygen.get_template(name='boundary_bottomleft'), gridname=pg)
    ispace = laygen.place(name="I" + objectname_pfix + 'SP0',
                          templatename=space_name,
                          gridname=pg,
                          xy=space_origin,
                          template_libname=workinglib)
    xy0 = laygen.get_xy(obj=laygen.get_template(name=space_name,
                                                libname=workinglib),
                        gridname=pg)
    xsp = xy0[0]
    #ysp=xy0[1]
    m_bnd = int(xsp / laygen.get_xy(
        obj=laygen.get_template(name='boundary_bottom'), gridname=pg)[0])
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=['nmos4_fast_left', 'pmos4_fast_left'],
                            transform_left=['R0', 'MX'],
                            devname_right=['nmos4_fast_right', 'pmos4_fast_right'],
                            transform_right=['R0', 'MX'],
                            origin=origin)
    #pins
    space_template = laygen.templates.get_template(space_name, workinglib)
    space_pins = space_template.pins
    space_origin_phy = ispace.bbox[0]
    vddcnt = 0
    vsscnt = 0
    for pn, p in space_pins.items():
        if pn.startswith('VDD'):
            laygen.add_pin('VDD' + str(vddcnt), 'VDD',
                           space_origin_phy + p['xy'], p['layer'])
            vddcnt += 1
        if pn.startswith('VSS'):
            laygen.add_pin('VSS' + str(vsscnt), 'VSS',
                           space_origin_phy + p['xy'], p['layer'])
            vsscnt += 1
Example #3
0
def generate_cap_wbnd(laygen,
                      objectname_pfix,
                      workinglib,
                      cap_name,
                      placement_grid,
                      m=1,
                      shape=np.array([1, 1]),
                      origin=np.array([0, 0])):
    cap_origin = origin + laygen.get_template_size('boundary_bottomleft', pg)
    icap = []
    for i in range(m):
        if i == 0:
            icap.append(
                laygen.place(name="I" + objectname_pfix + 'SP0',
                             templatename=cap_name,
                             gridname=pg,
                             xy=cap_origin,
                             shape=shape,
                             template_libname=workinglib))
        else:
            if i % 2 == 0:
                icap.append(
                    laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i),
                                    templatename=cap_name,
                                    gridname=pg,
                                    refinstname=icap[-1].name,
                                    shape=shape,
                                    template_libname=workinglib,
                                    direction='top'))
            else:
                icap.append(
                    laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i),
                                    templatename=cap_name,
                                    gridname=pg,
                                    refinstname=icap[-1].name,
                                    shape=shape,
                                    template_libname=workinglib,
                                    direction='top',
                                    transform='MX'))
    xy0 = laygen.get_template_size(
        name=cap_name, gridname=pg, libname=workinglib) * shape
    xsp = xy0[0]
    #ysp=xy0[1]
    m_bnd = int(xsp /
                laygen.get_template_size('boundary_bottom', gridname=pg)[0])
    devname_left = []
    devname_right = []
    transform_left = []
    transform_right = []
    for i in range(m):
        if i % 2 == 0:
            devname_left += ['nmos4_fast_left', 'pmos4_fast_left']
            devname_right += ['nmos4_fast_right', 'pmos4_fast_right']
            transform_left += ['R0', 'MX']
            transform_right += ['R0', 'MX']
        else:
            devname_left += ['pmos4_fast_left', 'nmos4_fast_left']
            devname_right += ['pmos4_fast_right', 'nmos4_fast_right']
            transform_left += ['MX', 'R0']
            transform_right += ['MX', 'R0']
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=devname_left,
                            transform_left=transform_left,
                            devname_right=devname_right,
                            transform_right=transform_right,
                            origin=origin)
    pdict_m3m4_thick = laygen.get_inst_pin_coord(None, None, rg_m3m4_thick)
    for i in range(int((m + 1) / 2)):
        pxyvdd = pdict_m3m4_thick[icap[i * 2].name]['VDD']
        pxyvdd[1] = pxyvdd[0] + (pxyvdd[1] - pxyvdd[0]) * shape
        pxyvss = pdict_m3m4_thick[icap[i * 2].name]['VSS']
        pxyvss[1] = pxyvss[0] + (pxyvss[1] - pxyvss[0]) * shape
        laygen.pin('VDD' + str(i),
                   laygen.layers['pin'][4],
                   pdict_m3m4_thick[icap[i * 2].name]['VDD'],
                   gridname=rg_m3m4_thick,
                   netname='VDD')
        laygen.pin('VSS' + str(i),
                   laygen.layers['pin'][4],
                   pdict_m3m4_thick[icap[i * 2].name]['VSS'],
                   gridname=rg_m3m4_thick,
                   netname='VSS')
    cap_template = laygen.templates.get_template(cap_name, workinglib)
    cap_pins = cap_template.pins
    if 'I' in cap_pins:
        if m == 1:
            laygen.pin('I',
                       laygen.layers['pin'][4],
                       pdict_m3m4_thick[icap[i].name]['I'],
                       gridname=rg_m3m4_thick)
        else:
            for i in range(int(m)):
                laygen.pin('I<' + str(i) + '>',
                           laygen.layers['pin'][4],
                           pdict_m3m4_thick[icap[i].name]['I'],
                           gridname=rg_m3m4_thick)
Example #4
0
def generate_tisaradc_space(laygen,
                            objectname_pfix,
                            tisar_libname,
                            space_libname,
                            tisar_name,
                            space_name,
                            placement_grid,
                            routing_grid_m3m4_thick,
                            routing_grid_m4m5_thick,
                            routing_grid_m5m6_thick,
                            origin=np.array([0, 0])):
    """generate tisar space """
    pg = placement_grid
    ttisar = laygen.templates.get_template(tisar_name, libname=tisar_libname)
    tspace = laygen.templates.get_template(space_name, libname=space_libname)
    tbnd_bottom = laygen.templates.get_template('boundary_bottom')
    tbnd_bleft = laygen.templates.get_template('boundary_bottomleft')
    space_xy = np.array([tspace.size[0], ttisar.size[1]])
    laygen.add_rect(
        None,
        np.array([
            origin,
            origin + space_xy + 2 * tbnd_bleft.size[0] * np.array([1, 0])
        ]), laygen.layers['prbnd'])
    num_space = int(
        (ttisar.size[1] - 2 * tbnd_bottom.size[1]) / tspace.size[1])
    #space_xy=np.array([tspace.size[0], 56.88]) #change it after finishing the clock part
    #num_space=int((56.88-2*tbnd_bottom.size[1])/tspace.size[1]) #should be changed after finishing the clock part
    space_origin = origin + laygen.get_template_size('boundary_bottomleft', pg)
    ispace = [
        laygen.place(name="I" + objectname_pfix + 'SP0',
                     templatename=space_name,
                     gridname=pg,
                     xy=space_origin,
                     template_libname=space_libname)
    ]
    #devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left']
    #devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right']
    devname_bnd_left = ['ptap_fast_left', 'ntap_fast_left']
    devname_bnd_right = ['ptap_fast_right', 'ntap_fast_right']
    transform_bnd_left = ['R0', 'MX']
    transform_bnd_right = ['R0', 'MX']
    for i in range(1, num_space):
        if i % 2 == 0:
            ispace.append(
                laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i),
                                templatename=space_name,
                                gridname=pg,
                                refinstname=ispace[-1].name,
                                direction='top',
                                transform='R0',
                                template_libname=space_libname))
            #devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left']
            #devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right']
            devname_bnd_left += ['ptap_fast_left', 'ntap_fast_left']
            devname_bnd_right += ['ptap_fast_right', 'ntap_fast_right']
            transform_bnd_left += ['R0', 'MX']
            transform_bnd_right += ['R0', 'MX']
        else:
            ispace.append(
                laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i),
                                templatename=space_name,
                                gridname=pg,
                                refinstname=ispace[-1].name,
                                direction='top',
                                transform='MX',
                                template_libname=space_libname))
            #devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left']
            #devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right']
            devname_bnd_left += ['ntap_fast_left', 'ptap_fast_left']
            devname_bnd_right += ['ntap_fast_right', 'ptap_fast_right']
            transform_bnd_left += ['R0', 'MX']
            transform_bnd_right += ['R0', 'MX']
            #transform_bnd_left +=  ['MX', 'R0']
            #transform_bnd_right += ['MX', 'R0']

    m_bnd = int(space_xy[0] / tbnd_bottom.size[0])
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=devname_bnd_left,
                            transform_left=transform_bnd_left,
                            devname_right=devname_bnd_right,
                            transform_right=transform_bnd_right,
                            origin=origin)
    #vdd/vss
    #m3
    rvdd_xy_m3 = []
    rvss_xy_m3 = []
    space_template = laygen.templates.get_template(space_name, workinglib)
    space_pins = space_template.pins
    space_origin_phy = laygen.get_inst_bbox_phygrid(ispace[0].name)[0]
    vddcnt = 0
    vsscnt = 0
    for pn, p in space_pins.items():
        if pn.startswith('VDD'):
            pxy = space_origin_phy + np.array(
                [p['xy'][0], p['xy'][1] * np.array([1, num_space])])
            laygen.add_rect(None, pxy, p['layer'])
            rvdd_xy_m3.append(
                laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick,
                                                      xy0=pxy[0],
                                                      xy1=pxy[1]))
            vddcnt += 1
        if pn.startswith('VSS'):
            pxy = space_origin_phy + np.array(
                [p['xy'][0], p['xy'][1] * np.array([1, num_space])])
            laygen.add_rect(None, pxy, p['layer'])
            rvss_xy_m3.append(
                laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick,
                                                      xy0=pxy[0],
                                                      xy1=pxy[1]))
            vsscnt += 1
    #m4
    input_rails_xy = [rvdd_xy_m3, rvss_xy_m3]
    rvdd_m4, rvss_m4 = laygenhelper.generate_power_rails_from_rails_xy(
        laygen,
        routename_tag='_M4_',
        layer=laygen.layers['metal'][4],
        gridname=rg_m3m4_thick,
        netnames=['VDD', 'VSS'],
        direction='x',
        input_rails_xy=input_rails_xy,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        overwrite_num_routes=80,
        offset_start_index=0,
        offset_end_index=0)
    #exclude_phycoord_list=[[23.4,34.7]])
    #m5
    input_rails_rect = [rvdd_m4, rvss_m4]
    rvdd_m5, rvss_m5 = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M5_',
        layer=laygen.layers['metal'][5],
        gridname=rg_m4m5_thick,
        netnames=['VDD', 'VSS'],
        direction='y',
        input_rails_rect=input_rails_rect,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    #m6 (extract VDD/VSS grid from tisar and make power pins)
    rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VDD'
    laygenhelper.generate_grids_from_template(
        laygen,
        gridname_input=rg_m5m6_thick,
        gridname_output=rg_m5m6_thick_temp_tisar,
        template_name=tisar_name,
        template_libname=tisar_libname,
        template_pin_prefix=['VDD'],
        xy_grid_type='ygrid')
    input_rails_rect = [rvdd_m5]
    rvdd_m6 = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_',
        layer=laygen.layers['pin'][6],
        gridname=rg_m5m6_thick_temp_tisar,
        netnames=['VDD'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=True,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=-1)
    rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VSS'
    laygenhelper.generate_grids_from_template(
        laygen,
        gridname_input=rg_m5m6_thick,
        gridname_output=rg_m5m6_thick_temp_tisar,
        template_name=tisar_name,
        template_libname=tisar_libname,
        template_pin_prefix=['VSS'],
        xy_grid_type='ygrid')
    input_rails_rect = [rvss_m5]
    rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_',
        layer=laygen.layers['pin'][6],
        gridname=rg_m5m6_thick_temp_tisar,
        netnames=['VSS'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=True,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=-2)
Example #5
0
def generate_tisaradc_space2(laygen,
                             objectname_pfix,
                             tisar_libname,
                             space_libname,
                             tisar_name,
                             space_name,
                             placement_grid,
                             routing_grid_m3m4_thick,
                             routing_grid_m4m5_thick,
                             routing_grid_m5m6_thick,
                             origin=np.array([0, 0])):
    """generate tisar space """
    pg = placement_grid
    ttisar = laygen.templates.get_template(tisar_name, libname=tisar_libname)
    tspace = laygen.templates.get_template(space_name, libname=space_libname)

    sar_pins = ttisar.pins

    tbnd_bottom = laygen.templates.get_template('boundary_bottom')
    tbnd_bleft = laygen.templates.get_template('boundary_bottomleft')
    space_xy = np.array([tspace.size[0], ttisar.size[1]])
    laygen.add_rect(
        None,
        np.array([
            origin,
            origin + space_xy + 2 * tbnd_bleft.size[0] * np.array([1, 0])
        ]), laygen.layers['prbnd'])
    num_space_tot = int(
        (ttisar.size[1] - 2 * tbnd_bottom.size[1]) / tspace.size[1])
    tbnd_bleft_size = tbnd_bleft.size

    #VDD/VSS/VREF integration
    rvddclkd = []
    rvddsamp = []
    rvddsar = []
    rvddsar_upper = []
    rvref0 = []
    rvref1 = []
    rvref2 = []
    rvssclkd = []
    rvsssamp = []
    rvsssar = []
    rvsssar_upper = []
    vddclkd_xy = []
    vddsamp_xy = []
    vddsar_xy = []
    vddsar_upper_xy = []
    vssclkd_xy = []
    vsssamp_xy = []
    vsssar_xy = []
    vsssar_upper_xy = []
    y_vddsar_max = 0
    y_vddsar_lower_max = 0
    y_vddsamp_min = 500000
    y_vddsamp_max = 0
    y_vddclkd_min = 500000
    y_vref0 = sar_pins['VREF0<0>']['xy'][0][1]

    #categorize vdd pins and figure out thresholds
    for pn, p in sar_pins.items():
        '''
        if pn.startswith('VDDCLKD'):
            pxy=np.array([[0, sar_pins[pn]['xy'][0][1]], 
                          [2*tbnd_bleft_size[0]+space_xy[0], sar_pins[pn]['xy'][1][1]]])
            rvddclkd.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
            if pxy[1][1]<y_vddclkd_min:
                y_vddclkd_min=pxy[1][1]
            vddclkd_xy.append(pxy)
        '''
        if pn.startswith('VDDSAMP'):
            pxy = np.array([[0, sar_pins[pn]['xy'][0][1]],
                            [
                                2 * tbnd_bleft_size[0] + space_xy[0],
                                sar_pins[pn]['xy'][1][1]
                            ]])
            rvddsamp.append(
                laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
            if pxy[1][1] < y_vddsamp_min:
                y_vddsamp_min = pxy[1][1]
            if pxy[1][1] > y_vddsamp_max:
                y_vddsamp_max = pxy[1][1]
            vddsamp_xy.append(pxy)
        if pn.startswith('VDDSAR'):
            pxy = np.array([[0, sar_pins[pn]['xy'][0][1]],
                            [
                                2 * tbnd_bleft_size[0] + space_xy[0],
                                sar_pins[pn]['xy'][1][1]
                            ]])
            if pxy[0][1] > y_vref0:
                rvddsar_upper.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
                vddsar_upper_xy.append(pxy)
            else:
                rvddsar.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
                vddsar_xy.append(pxy)
                if pxy[1][1] > y_vddsar_lower_max:
                    y_vddsar_lower_max = pxy[1][1]
            if pxy[1][1] > y_vddsar_max:
                y_vddsar_max = pxy[1][1]
        if pn.startswith('VREF'):
            pxy = np.array([[0, sar_pins[pn]['xy'][0][1]],
                            [
                                2 * tbnd_bleft_size[0] + space_xy[0],
                                sar_pins[pn]['xy'][1][1]
                            ]])
            if pn.endswith('<0>'):
                rvref0.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
            if pn.endswith('<1>'):
                rvref1.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
            if pn.endswith('<2>'):
                rvref2.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
    y_vss_th = 0.5 * (y_vddsar_max + y_vddsamp_min
                      )  #find out threshold (sar/samp)
    #y_vss_th2=0.5*(y_vddsamp_max+y_vddclkd_min) #(samp/clkd)
    y_vss_th2 = 100000
    for pn, p in sar_pins.items():
        if pn.startswith('VSS'):
            pxy = np.array([[0, sar_pins[pn]['xy'][0][1]],
                            [
                                2 * tbnd_bleft_size[0] + space_xy[0],
                                sar_pins[pn]['xy'][1][1]
                            ]])
            if pxy[0][1] > y_vss_th2:
                rvssclkd.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
                vssclkd_xy.append(pxy)
            elif pxy[0][1] > y_vss_th:
                rvsssamp.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
                vsssamp_xy.append(pxy)
            elif pxy[0][1] > y_vref0:
                rvsssar_upper.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
                vsssar_upper_xy.append(pxy)
            else:
                rvsssar.append(
                    laygen.add_rect(None, pxy, laygen.layers['metal'][6]))
                vsssar_xy.append(pxy)

    #vddsar cap
    num_space_sar = int(
        (y_vss_th - 2 * tbnd_bottom.size[1]) / tspace.size[1]) + 4
    space_origin = origin + laygen.get_template_size('boundary_bottomleft', pg)
    ispace_sar = [
        laygen.place(name="I" + objectname_pfix + 'SPSAR0',
                     templatename=space_name,
                     gridname=pg,
                     xy=space_origin,
                     template_libname=space_libname)
    ]
    devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left']
    devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right']
    transform_bnd_left = ['R0', 'MX']
    transform_bnd_right = ['R0', 'MX']

    for i in range(1, num_space_sar):
        if i % 2 == 0:
            ispace_sar.append(
                laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(i),
                                templatename=space_name,
                                gridname=pg,
                                refinstname=ispace_sar[-1].name,
                                direction='top',
                                transform='R0',
                                template_libname=space_libname))
            devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left']
            devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right']
            transform_bnd_left += ['R0', 'MX']
            transform_bnd_right += ['R0', 'MX']
        else:
            ispace_sar.append(
                laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(i),
                                templatename=space_name,
                                gridname=pg,
                                refinstname=ispace_sar[-1].name,
                                direction='top',
                                transform='MX',
                                template_libname=space_libname))
            devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left']
            devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right']
            transform_bnd_left += ['R0', 'MX']
            transform_bnd_right += ['R0', 'MX']

    m_bnd = int(space_xy[0] / tbnd_bottom.size[0])
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAR0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=devname_bnd_left,
                            transform_left=transform_bnd_left,
                            devname_right=devname_bnd_right,
                            transform_right=transform_bnd_right,
                            origin=origin)

    #vddsamp cap
    num_space_samp = num_space_tot - num_space_sar - 1
    space_origin = origin + laygen.get_template_size(
        'boundary_bottomleft', pg) * np.array([1, (3 + 2 * num_space_sar)])
    ispace_samp = [
        laygen.place(name="I" + objectname_pfix + 'SPSAMP0',
                     templatename=space_name,
                     gridname=pg,
                     xy=space_origin,
                     template_libname=space_libname)
    ]
    devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left']
    devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right']
    transform_bnd_left = ['R0', 'MX']
    transform_bnd_right = ['R0', 'MX']

    for i in range(1, num_space_samp):
        if i % 2 == 0:
            ispace_samp.append(
                laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i),
                                templatename=space_name,
                                gridname=pg,
                                refinstname=ispace_samp[-1].name,
                                direction='top',
                                transform='R0',
                                template_libname=space_libname))
            devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left']
            devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right']
            transform_bnd_left += ['R0', 'MX']
            transform_bnd_right += ['R0', 'MX']
        else:
            ispace_samp.append(
                laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i),
                                templatename=space_name,
                                gridname=pg,
                                refinstname=ispace_samp[-1].name,
                                direction='top',
                                transform='MX',
                                template_libname=space_libname))
            devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left']
            devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right']
            transform_bnd_left += ['R0', 'MX']
            transform_bnd_right += ['R0', 'MX']

    m_bnd = int(space_xy[0] / tbnd_bottom.size[0])
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAMP0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=devname_bnd_left,
                            transform_left=transform_bnd_left,
                            devname_right=devname_bnd_right,
                            transform_right=transform_bnd_right,
                            origin=space_origin-laygen.get_template_size('boundary_bottomleft', pg))
    #vdd/vss
    #m3
    rvdd_sar_xy_m3 = []
    rvss_sar_xy_m3 = []
    space_template = laygen.templates.get_template(space_name, workinglib)
    space_pins = space_template.pins
    space_origin_phy = laygen.get_inst_bbox_phygrid(ispace_sar[0].name)[0]
    vddcnt = 0
    vsscnt = 0
    for pn, p in space_pins.items():
        if pn.startswith('VDD'):
            pxy = space_origin_phy + np.array(
                [p['xy'][0], p['xy'][1] * np.array([1, num_space_sar])])
            pxy[1][1] = y_vddsar_lower_max
            laygen.add_rect(None, pxy, laygen.layers['metal'][3])
            rvdd_sar_xy_m3.append(
                laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick,
                                                      xy0=pxy[0],
                                                      xy1=pxy[1]))
            vddcnt += 1
        if pn.startswith('VSS'):
            pxy = space_origin_phy + np.array(
                [p['xy'][0], p['xy'][1] * np.array([1, num_space_sar])])
            pxy[1][1] = y_vddsar_lower_max
            laygen.add_rect(None, pxy, laygen.layers['metal'][3])
            rvss_sar_xy_m3.append(
                laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick,
                                                      xy0=pxy[0],
                                                      xy1=pxy[1]))
            vsscnt += 1
    rvdd_samp_xy_m3 = []
    rvss_samp_xy_m3 = []
    space_template = laygen.templates.get_template(space_name, workinglib)
    space_pins = space_template.pins
    space_origin_phy = laygen.get_inst_bbox_phygrid(ispace_samp[0].name)[0]
    vddcnt = 0
    vsscnt = 0
    for pn, p in space_pins.items():
        if pn.startswith('VDD'):
            pxy = space_origin_phy + np.array(
                [p['xy'][0], p['xy'][1] * np.array([1, num_space_samp])])
            laygen.add_rect(None, pxy, laygen.layers['metal'][3])
            rvdd_samp_xy_m3.append(
                laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick,
                                                      xy0=pxy[0],
                                                      xy1=pxy[1]))
            vddcnt += 1
        if pn.startswith('VSS'):
            pxy = space_origin_phy + np.array(
                [p['xy'][0], p['xy'][1] * np.array([1, num_space_samp])])
            laygen.add_rect(None, pxy, laygen.layers['metal'][3])
            rvss_samp_xy_m3.append(
                laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick,
                                                      xy0=pxy[0],
                                                      xy1=pxy[1]))
            vsscnt += 1
    #m4
    input_rails_xy = [rvdd_samp_xy_m3, rvss_samp_xy_m3]
    rvdd_samp_m4, rvss_samp_m4 = laygenhelper.generate_power_rails_from_rails_xy(
        laygen,
        routename_tag='_M4_SAMP_',
        layer=laygen.layers['metal'][4],
        gridname=rg_m3m4_thick,
        netnames=['VDDSAMP', 'VSSSAMP'],
        direction='x',
        input_rails_xy=input_rails_xy,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    input_rails_xy = [rvdd_sar_xy_m3, rvss_sar_xy_m3]
    rvdd_sar_m4, rvss_sar_m4 = laygenhelper.generate_power_rails_from_rails_xy(
        laygen,
        routename_tag='_M4_SAR_',
        layer=laygen.layers['metal'][4],
        gridname=rg_m3m4_thick,
        netnames=['VDDSAR', 'VSSSAR'],
        direction='x',
        input_rails_xy=input_rails_xy,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    #m5
    input_rails_rect = [rvdd_samp_m4, rvss_samp_m4]
    rvdd_samp_m5, rvss_samp_m5 = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M5_SAMP',
        layer=laygen.layers['metal'][5],
        gridname=rg_m4m5_thick,
        netnames=['VDD', 'VSS'],
        direction='y',
        input_rails_rect=input_rails_rect,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    input_rails_rect = [rvdd_sar_m4, rvss_sar_m4]
    rvdd_sar_m5, rvss_sar_m5 = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M5_SAR',
        layer=laygen.layers['metal'][5],
        gridname=rg_m4m5_thick,
        netnames=['VDD', 'VSS'],
        direction='y',
        input_rails_rect=input_rails_rect,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)

    #m6 (extract VDD/VSS grid from tisar and make power pins)
    rg_m5m6_sar_vdd = 'route_M5_M6_thick_temp_tisar_sar_vdd'
    laygenhelper.generate_grids_from_xy(laygen,
                                        gridname_input=rg_m5m6_thick,
                                        gridname_output=rg_m5m6_sar_vdd,
                                        xy=vddsar_xy,
                                        xy_grid_type='ygrid')
    input_rails_rect = [rvdd_sar_m5]
    [rvdd_sar_m6] = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_SAR_',
        layer=laygen.layers['pin'][6],
        gridname=rg_m5m6_sar_vdd,
        netnames=['VDDSAR'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=True,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)

    rg_m5m6_sar_vss = 'route_M5_M6_thick_temp_tisar_sar_vss'
    laygenhelper.generate_grids_from_xy(laygen,
                                        gridname_input=rg_m5m6_thick,
                                        gridname_output=rg_m5m6_sar_vss,
                                        xy=vsssar_xy,
                                        xy_grid_type='ygrid')
    input_rails_rect = [rvss_sar_m5]
    [rvss_sar_m6] = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_SAR_',
        layer=laygen.layers['pin'][6],
        gridname=rg_m5m6_sar_vss,
        netnames=['VSS:'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=True,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)

    rg_m5m6_samp = 'route_M5_M6_thick_temp_tisar_samp_vdd'
    laygenhelper.generate_grids_from_xy(laygen,
                                        gridname_input=rg_m5m6_thick,
                                        gridname_output=rg_m5m6_samp,
                                        xy=vddsamp_xy,
                                        xy_grid_type='ygrid')
    input_rails_rect = [rvdd_samp_m5]
    [rvdd_samp_m6] = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_SAMP_',
        layer=laygen.layers['pin'][6],
        gridname=rg_m5m6_samp,
        netnames=['VDDSAMP'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=True,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    rg_m5m6_samp = 'route_M5_M6_thick_temp_tisar_samp_vss'
    laygenhelper.generate_grids_from_xy(laygen,
                                        gridname_input=rg_m5m6_thick,
                                        gridname_output=rg_m5m6_samp,
                                        xy=vsssamp_xy,
                                        xy_grid_type='ygrid')
    input_rails_rect = [rvss_samp_m5]
    [rvss_samp_m6] = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_SAMP_',
        layer=laygen.layers['pin'][6],
        gridname=rg_m5m6_samp,
        netnames=['VSS:'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=True,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    '''
    rg_m5m6_clkd='route_M5_M6_thick_temp_tisar_clkd'
    laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_clkd, xy=vddclkd_xy + vssclkd_xy, xy_grid_type='ygrid')
    input_rails_rect = [rvdd_samp_m5, rvss_samp_m5]
    [rvdd_clkd_m6, rvss_clkd_m6] = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_CLKD_', 
                            layer=laygen.layers['pin'][6], gridname=rg_m5m6_clkd, netnames=['VDDSAMP', 'VSS:'], direction='x', 
                            input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None,
                            offset_start_index=0, offset_end_index=0)
    '''
    print(num_space_sar, num_space_samp)

    yamlfile_output = "adc_sar_size.yaml"
    #write to file
    with open(yamlfile_output, 'r') as stream:
        outdict = yaml.load(stream)
    outdict['num_space_sar'] = num_space_sar
    outdict['num_space_samp'] = num_space_samp
    with open(yamlfile_output, 'w') as stream:
        yaml.dump(outdict, stream)
Example #6
0
def generate_samp(laygen,
                  objectname_pfix,
                  workinglib,
                  placement_grid='placement_basic',
                  routing_grid_m4m5='route_M4_M5_basic_thick',
                  power_grid_m3m4='route_M3_M4_basic_thick',
                  power_grid_m4m5='route_M4_M5_thick',
                  power_grid_m5m6='route_M5_M6_thick',
                  origin=np.array([0, 0])):
    """generate a sampler with clock buffers. used when AnalogMOS is not available
    """
    #variable/cell namings
    pg = placement_grid
    rg45bt = routing_grid_m4m5
    pg34bt = power_grid_m3m4
    pg45t = power_grid_m4m5
    pg56t = power_grid_m5m6

    # placement
    core_origin = origin + laygen.get_xy(
        obj=laygen.get_template(name='boundary_bottomleft'), gridname=pg)
    # sampler body
    isamp = laygen.relplace(name=None,
                            templatename='sarsamp_body',
                            gridname=pg,
                            template_libname=workinglib,
                            transform='R0',
                            xy=core_origin)
    # clock buffer
    if tgate == True:
        ibuf = laygen.relplace(name=None,
                               templatename='sarsamp_buf',
                               gridname=pg,
                               refobj=isamp,
                               direction='top',
                               template_libname=workinglib,
                               transform='MX')
    else:
        ibuf = laygen.relplace(name=None,
                               templatename='sarsamp_buf',
                               gridname=pg,
                               refobj=isamp,
                               direction='top',
                               template_libname=workinglib,
                               transform='R0')
    # boundaries
    a = laygen.get_xy(obj=laygen.get_template(name='sarsamp_body',
                                              libname=workinglib),
                      gridname=pg)[0]
    b = laygen.get_xy(obj=laygen.get_template(name='boundary_bottom'),
                      gridname=pg)[0]
    m_bnd = int(a / b)
    if tgate == True:
        devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'
                            ] + ['pmos4_fast_left', 'nmos4_fast_left']
        devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'
                             ] + ['pmos4_fast_right', 'nmos4_fast_right']
        transform_bnd_left = ['R0', 'MX'] + ['MX', 'R0']
        transform_bnd_right = ['R0', 'MX'] + ['MX', 'R0']
    else:
        devname_bnd_left = ['nmos4_fast_left', 'nmos4_fast_left'
                            ] + ['nmos4_fast_left', 'pmos4_fast_left']
        devname_bnd_right = ['nmos4_fast_right', 'nmos4_fast_right'
                             ] + ['nmos4_fast_right', 'pmos4_fast_right']
        transform_bnd_left = ['R0', 'MX'] + ['R0', 'MX']
        transform_bnd_right = ['R0', 'MX'] + ['R0', 'MX']
    [bnd_bottom, bnd_top, bnd_left, bnd_right] \
        = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg,
                            devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'],
                            shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'],
                            shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])],
                            devname_left=devname_bnd_left,
                            transform_left=transform_bnd_left,
                            devname_right=devname_bnd_right,
                            transform_right=transform_bnd_right,
                            origin=origin)

    # route
    x_center=int((laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[1][0] \
                  -laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[0][0])/2\
                  +laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[0][0])
    y_top = int(
        laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[1][1])
    #in
    xy0 = laygen.get_inst_pin_xy(name=isamp.name,
                                 pinname='IP',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = [x_center - 3, y_top]
    rh0, rinp0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt)
    xy0 = laygen.get_inst_pin_xy(name=isamp.name,
                                 pinname='IM',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = [x_center + 3, y_top]
    rh0, rinn0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt)
    #out
    xy0 = laygen.get_inst_pin_xy(name=isamp.name,
                                 pinname='OP',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = [x_center - 3, 0]
    rh0, routp0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt)
    xy0 = laygen.get_inst_pin_xy(name=isamp.name,
                                 pinname='OM',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = [x_center + 3, 0]
    rh0, routn0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt)
    #en
    xy0 = laygen.get_inst_pin_xy(name=ibuf.name,
                                 pinname='OUT_SW',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = laygen.get_inst_pin_xy(name=isamp.name,
                                 pinname='EN',
                                 gridname=rg45bt,
                                 sort=True)[0]
    rh0, rckpg0, rh1 = laygen.route_hvh(xy0=xy0,
                                        xy1=xy1,
                                        track_x=x_center - 1,
                                        gridname0=rg45bt)
    rh0, rv0, rh1 = laygen.route_hvh(xy0=xy0,
                                     xy1=xy1,
                                     track_x=x_center + 1,
                                     gridname0=rg45bt)
    #enb
    if tgate == True:
        xy0 = laygen.get_inst_pin_xy(name=ibuf.name,
                                     pinname='out_int<0>',
                                     gridname=rg45bt,
                                     sort=True)[0]
        xy1 = laygen.get_inst_pin_xy(name=isamp.name,
                                     pinname='ENB',
                                     gridname=rg45bt,
                                     sort=True)[0]
        rh0, rckint0, rh1 = laygen.route_hvh(xy0=xy0,
                                             xy1=xy1,
                                             track_x=x_center - 2,
                                             gridname0=rg45bt)
        rh0, rv0, rh1 = laygen.route_hvh(xy0=xy0,
                                         xy1=xy1,
                                         track_x=x_center + 2,
                                         gridname0=rg45bt)
    #ckin
    xy0 = laygen.get_inst_pin_xy(name=ibuf.name,
                                 pinname='IN',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = [xy0[0], y_top]
    rh0, rckin0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt)
    #ckout
    xy0 = laygen.get_inst_pin_xy(name=ibuf.name,
                                 pinname='OUT_BUF',
                                 gridname=rg45bt,
                                 sort=True)[0]
    xy1 = [x_center, 0]
    rh0, rckout0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt)

    # signal pins
    for p, r in zip(['inp', 'inn', 'outp', 'outn', 'ckin', 'ckout', 'ckpg'],
                    [rinp0, rinn0, routp0, routn0, rckin0, rckout0, rckpg0]):
        laygen.pin(name=p,
                   layer=laygen.layers['pin'][5],
                   refobj=r,
                   gridname=rg45bt)

    #vdd/vss - route
    #samp_m3_xy
    rvss_samp_m3 = [[], []]
    for pn, p in laygen.get_inst(isamp.name).pins.items():
        if pn.startswith('VSSL'):
            xy = laygen.get_inst_pin_xy(name=isamp.name,
                                        pinname=pn,
                                        gridname=pg34bt,
                                        sort=True)
            rvss_samp_m3[0].append(xy)
        if pn.startswith('VSSR'):
            xy = laygen.get_inst_pin_xy(name=isamp.name,
                                        pinname=pn,
                                        gridname=pg34bt,
                                        sort=True)
            rvss_samp_m3[1].append(xy)
    #samp_m4
    rvss_samp_m4 = [None, None]
    input_rails_xy = [rvss_samp_m3[0]]
    rvss_samp_m4[0] = laygenhelper.generate_power_rails_from_rails_xy(
        laygen,
        routename_tag='_SAMPL_M4_',
        layer=laygen.layers['metal'][4],
        gridname=pg34bt,
        netnames=['VSS'],
        direction='x',
        input_rails_xy=input_rails_xy,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=-1)[0]
    input_rails_xy = [rvss_samp_m3[1]]
    rvss_samp_m4[1] = laygenhelper.generate_power_rails_from_rails_xy(
        laygen,
        routename_tag='_SAMPR_M4_',
        layer=laygen.layers['metal'][4],
        gridname=pg34bt,
        netnames=['VSS'],
        direction='x',
        input_rails_xy=input_rails_xy,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=-1)[0]
    #buf_m3_xy
    rvdd_buf_m3 = [[], []]
    rvss_buf_m3 = [[], []]
    for pn, p in laygen.get_inst(ibuf.name).pins.items():
        if pn.startswith('VSSL'):
            xy = laygen.get_inst_pin_xy(name=ibuf.name,
                                        pinname=pn,
                                        gridname=pg34bt,
                                        sort=True)
            rvss_buf_m3[0].append(xy)
        if pn.startswith('VSSR'):
            xy = laygen.get_inst_pin_xy(name=ibuf.name,
                                        pinname=pn,
                                        gridname=pg34bt,
                                        sort=True)
            rvss_buf_m3[1].append(xy)
        if pn.startswith('VDDL'):
            xy = laygen.get_inst_pin_xy(name=ibuf.name,
                                        pinname=pn,
                                        gridname=pg34bt,
                                        sort=True)
            rvdd_buf_m3[0].append(xy)
        if pn.startswith('VDDR'):
            xy = laygen.get_inst_pin_xy(name=ibuf.name,
                                        pinname=pn,
                                        gridname=pg34bt,
                                        sort=True)
            rvdd_buf_m3[1].append(xy)
    #buf_m4
    rvss_buf_m4 = [None, None]
    rvdd_buf_m4 = [None, None]
    input_rails_xy = [rvdd_buf_m3[0], rvss_buf_m3[0]]
    rvdd_buf_m4[0], rvss_buf_m4[
        0] = laygenhelper.generate_power_rails_from_rails_xy(
            laygen,
            routename_tag='_BUFL_M4_',
            layer=laygen.layers['metal'][4],
            gridname=pg34bt,
            netnames=['VDD', 'VSS'],
            direction='x',
            input_rails_xy=input_rails_xy,
            generate_pin=False,
            overwrite_start_coord=None,
            overwrite_end_coord=None,
            offset_start_index=1,
            offset_end_index=0)
    input_rails_xy = [rvdd_buf_m3[1], rvss_buf_m3[1]]
    rvdd_buf_m4[1], rvss_buf_m4[
        1] = laygenhelper.generate_power_rails_from_rails_xy(
            laygen,
            routename_tag='_BUFR_M4_',
            layer=laygen.layers['metal'][4],
            gridname=pg34bt,
            netnames=['VDD', 'VSS'],
            direction='x',
            input_rails_xy=input_rails_xy,
            generate_pin=False,
            overwrite_start_coord=None,
            overwrite_end_coord=None,
            offset_start_index=1,
            offset_end_index=0)
    #m4
    rvss_m4 = [
        rvss_samp_m4[0] + rvss_buf_m4[0], rvss_samp_m4[1] + rvss_buf_m4[1]
    ]
    rvdd_m4 = rvdd_buf_m4
    #m5
    rvss_m5 = [None, None]
    rvdd_m5 = [None, None]
    input_rails_rect = [rvdd_m4[0], rvss_m4[0]]
    rvdd_m5[0], rvss_m5[0] = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='L_M5_',
        layer=laygen.layers['metal'][5],
        gridname=pg45t,
        netnames=['VDD', 'VSS'],
        direction='y',
        input_rails_rect=input_rails_rect,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    input_rails_rect = [rvdd_m4[1], rvss_m4[1]]
    rvdd_m5[1], rvss_m5[1] = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='R_M5_',
        layer=laygen.layers['metal'][5],
        gridname=pg45t,
        netnames=['VDD', 'VSS'],
        direction='y',
        input_rails_rect=input_rails_rect,
        generate_pin=False,
        overwrite_start_coord=None,
        overwrite_end_coord=None,
        offset_start_index=0,
        offset_end_index=0)
    #m6
    input_rails_rect = [rvdd_m5[0] + rvdd_m5[1], rvss_m5[0] + rvss_m5[1]]
    x1 = laygen.get_inst_bbox(
        name=ibuf.name, gridname=pg56t)[1][0] + laygen.get_xy(
            obj=laygen.get_template(name='nmos4_fast_left'), gridname=pg56t)[0]
    rvdd_m6, rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect(
        laygen,
        routename_tag='_M6_',
        layer=laygen.layers['metal'][6],
        gridname=pg56t,
        netnames=['VDD', 'VSS'],
        direction='x',
        input_rails_rect=input_rails_rect,
        generate_pin=False,
        overwrite_start_coord=0,
        overwrite_end_coord=x1,
        offset_start_index=0,
        offset_end_index=0)
    #trimming and pinning
    x1_phy = laygen.get_inst_bbox(name=ibuf.name)[1][0] + laygen.get_xy(
        obj=laygen.get_template(name='nmos4_fast_left'))[0]
    for r in rvdd_m6:
        r.xy1[0] = x1_phy
        p = laygen.pin(name='VDD_M6_' + r.name,
                       layer=laygen.layers['pin'][6],
                       refobj=r,
                       gridname=pg56t,
                       netname='VDD')
        p.xy1[0] = x1_phy
    for r in rvss_m6:
        r.xy1[0] = x1_phy
        p = laygen.pin(name='VSS_M6_' + r.name,
                       layer=laygen.layers['pin'][6],
                       refobj=r,
                       gridname=pg56t,
                       netname='VSS')
        p.xy1[0] = x1_phy