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'])
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
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)
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)
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)
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