def generate_tisaradc_body_core(laygen, objectname_pfix, ret_libname, sar_libname, clkdist_libname, space_1x_libname, ret_name, sar_name, clkdist_name, space_1x_name, placement_grid, routing_grid_m3m4, routing_grid_m4m5, routing_grid_m4m5_basic_thick, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, routing_grid_m6m7_thick, num_bits=9, num_slices=8, use_offset=True, clkin_trackm=12, clk_cdac_bits=5, clk_pulse=False, clkdist_offset=2, ret_use_laygo=True, use_sf=False, vref_sf=False, origin=np.array([0, 0])): """generate sar array """ pg = placement_grid rg_m3m4 = routing_grid_m3m4 rg_m4m5 = routing_grid_m4m5 rg_m4m5_basic_thick = routing_grid_m4m5_basic_thick rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic rg_m6m7_thick = routing_grid_m6m7_thick # placement space_size = laygen.templates.get_template(space_1x_name, libname=space_1x_libname).size # ret/sar/clk iret = laygen.place(name="I" + objectname_pfix + 'RET0', templatename=ret_name, gridname=pg, xy=origin, template_libname=ret_libname) sar_xy = origin + (laygen.get_xy(obj=laygen.get_template( name=ret_name, libname=ret_libname), gridname=pg) * np.array([0, 1])) isar = laygen.relplace(name="I" + objectname_pfix + 'SAR0', templatename=sar_name, gridname=pg, refinstname=iret.name, direction='top', template_libname=sar_libname) # clkdist_offset_pg=int(clkdist_offset*space_size[1]/laygen.get_grid(pg).height) # clkdist_xy = laygen.get_xy(obj =isar, gridname=pg) \ # + (laygen.get_xy(obj=laygen.get_template(name = sar_name, libname=sar_libname), gridname=pg) * np.array([0, 1])) \ # + np.array([0, clkdist_offset_pg]) clkdist_xy = laygen.templates.get_template(clkdist_name, libname=clkdist_libname).xy clkdist_off_y = laygen.grids.get_absgrid_y(pg, clkdist_xy[0][1]) clkdist_off_y_voff_route_phy = int(laygen.grids.get_phygrid_y(rg_m5m6, num_hori * num_vert+4) / \ laygen.get_template_size('space_1x', gridname=None, libname=logictemplib)[1]+1) * \ laygen.get_template_size('space_1x', gridname=None, libname=logictemplib)[1] clkdist_off_y_voff_route = laygen.grids.get_absgrid_y( pg, clkdist_off_y_voff_route_phy) iclkdist = laygen.relplace( name="I" + objectname_pfix + 'CLKDIST0', templatename=clkdist_name, gridname=pg, refinstname=isar.name, direction='top', xy=[0, -clkdist_off_y + clkdist_off_y_voff_route], template_libname=clkdist_libname) sar_template = laygen.templates.get_template(sar_name, sar_libname) sar_pins = sar_template.pins sar_xy = isar.xy ret_template = laygen.templates.get_template(ret_name, ret_libname) ret_pins = ret_template.pins ret_xy = iret.xy clkdist_template = laygen.templates.get_template(clkdist_name, clkdist_libname) clkdist_pins = clkdist_template.pins clkdist_xy = iclkdist.xy #prboundary sar_size = laygen.templates.get_template(sar_name, libname=sar_libname).size ret_size = laygen.templates.get_template(ret_name, libname=ret_libname).size clkdist_size = laygen.templates.get_template(clkdist_name, libname=clkdist_libname).size size_x = max((sar_size[0], ret_size[0])) print(sar_size[1] + ret_size[1] + clkdist_size[1], sar_size[1], ret_size[1], clkdist_size[1], space_size[1]) size_y = int((sar_size[1] + ret_size[1] + clkdist_size[1]) / space_size[1] + 1 + clkdist_offset) * space_size[1] laygen.add_rect(None, np.array([origin, origin + np.array([size_x, size_y])]), laygen.layers['prbnd']) pdict_m2m3 = laygen.get_inst_pin_xy(None, None, rg_m2m3) pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4) pdict_m4m5 = laygen.get_inst_pin_xy(None, None, rg_m4m5) pdict_m4m5_basic_thick = laygen.get_inst_pin_xy(None, None, rg_m4m5_basic_thick) pdict_m4m5_thick = laygen.get_inst_pin_xy(None, None, rg_m4m5_thick) pdict_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6) pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) pdict_m5m6_thick_basic = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_basic) #VDD/VSS pins for sar and ret (just duplicate from lower hierarchy cells) vddsampcnt = 0 vddsarcnt = 0 vsscnt = 0 for pn, p in sar_pins.items(): if pn.startswith('VDDSAMP'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin('VDDSAMP' + str(vddsampcnt), 'VDDSAMP:', pxy, sar_pins[pn]['layer']) vddsampcnt += 1 if pn.startswith('VDDSAR'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin('VDDSAR' + str(vddsarcnt), 'VDDSAR:', pxy, sar_pins[pn]['layer']) vddsarcnt += 1 if pn.startswith('VSS'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin('VSS' + str(vsscnt), 'VSS:', pxy, sar_pins[pn]['layer']) if pn == 'VSS4': print(pn, vsscnt, p) vsscnt += 1 for pn, p in ret_pins.items(): if pn.startswith('VDD'): pxy = ret_xy + ret_pins[pn]['xy'] laygen.add_pin('VDDSAR' + str(vddsarcnt), 'VDDSAR:', pxy, ret_pins[pn]['layer']) vddsarcnt += 1 if pn.startswith('VSS'): pxy = ret_xy + ret_pins[pn]['xy'] laygen.add_pin('VSS' + str(vsscnt), 'VSS:', pxy, ret_pins[pn]['layer']) vsscnt += 1 for pn, p in clkdist_pins.items(): if pn.startswith('VDD'): pxy = clkdist_xy + clkdist_pins[pn]['xy'] laygen.add_pin('VDDSAMP' + str(vddsampcnt), 'VDDSAMP:', pxy, clkdist_pins[pn]['layer']) vddsampcnt += 1 if pn.startswith('VSS'): pxy = clkdist_xy + clkdist_pins[pn]['xy'] laygen.add_pin('VSS' + str(vsscnt), 'VSS:', pxy, clkdist_pins[pn]['layer']) vsscnt += 1 # #VDD/VSS pins for clkdist # rvdd_ckd_m5=[] # rvss_ckd_m5=[] # for i in range(num_slices): # rvdd, rvss = laygenhelper.generate_power_rails_from_rails_inst(laygen, routename_tag='', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], # direction='y', input_rails_instname=iclkdist.name, input_rails_pin_prefix=['VDD0_'+str(i), 'VSS0_'+str(i)], generate_pin=False, # overwrite_start_coord=None, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=1, offset_end_index=-1) # rvdd_ckd_m5+=rvdd # rvss_ckd_m5+=rvss # rvdd, rvss = laygenhelper.generate_power_rails_from_rails_inst(laygen, routename_tag='', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], # direction='y', input_rails_instname=iclkdist.name, input_rails_pin_prefix=['VDD1_'+str(i), 'VSS1_'+str(i)], generate_pin=False, # overwrite_start_coord=None, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=1, offset_end_index=-1) # rvdd_ckd_m5+=rvdd # rvss_ckd_m5+=rvss # laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick, netnames=['VDDSAMP:', 'VSS:'], direction='x', # input_rails_rect=[rvdd_ckd_m5, rvss_ckd_m5], generate_pin=True, # overwrite_start_coord=0, overwrite_end_coord=None, overwrite_num_routes=None, # offset_start_index=0, offset_end_index=0) #input pins if input_htree == False: #make virtual grids and route on the grids (assuming drc clearance of each block) rg_m5m6_thick_temp_sig = 'route_M5_M6_thick_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_sig, instname=isar.name, inst_pin_prefix=['INP', 'INM'], xy_grid_type='xgrid') pdict_m5m6_thick_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_temp_sig) inp_x_list = [] inm_x_list = [] num_input_track = 4 in_x0 = pdict_m5m6_thick_temp_sig[isar.name]['INP0'][0][0] in_x1 = pdict_m5m6_thick_temp_sig[isar.name]['INM0'][0][0] in_y0 = pdict_m5m6_thick_temp_sig[isar.name]['INP0'][0][1] in_y1 = in_y0 + 2 in_y2 = in_y1 + 2 * num_input_track for i in range(num_slices): in_x0 = min( in_x0, pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0]) in_x1 = max( in_x1, pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0]) laygen.route( None, laygen.layers['metal'][5], xy0=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0], in_y0 ]), xy1=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0], in_y2 ]), gridname0=rg_m5m6_thick_temp_sig) laygen.route( None, laygen.layers['metal'][5], xy0=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0], in_y0 ]), xy1=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0], in_y2 ]), gridname0=rg_m5m6_thick_temp_sig) for j in range(num_input_track): laygen.via( None, np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0], in_y1 + 2 * j ]), rg_m5m6_thick_temp_sig) laygen.via( None, np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0], in_y1 + 2 * j + 1 ]), rg_m5m6_thick_temp_sig) #in_x0 -= 2 #in_x1 += 2 rinp = [] rinm = [] for i in range(num_input_track): rinp.append( laygen.route(None, laygen.layers['metal'][6], xy0=np.array([in_x0, in_y1 + 2 * i]), xy1=np.array([in_x1, in_y1 + 2 * i]), gridname0=rg_m5m6_thick_temp_sig)) rinm.append( laygen.route(None, laygen.layers['metal'][6], xy0=np.array([in_x0, in_y1 + 2 * i + 1]), xy1=np.array([in_x1, in_y1 + 2 * i + 1]), gridname0=rg_m5m6_thick_temp_sig)) laygen.add_pin('INP' + str(i), 'INP', rinp[-1].xy, laygen.layers['pin'][6]) laygen.add_pin('INM' + str(i), 'INM', rinm[-1].xy, laygen.layers['pin'][6]) else: for i in range(num_slices): pn = 'INP' + str(i) laygen.pin(name=pn, layer=laygen.layers['pin'][5], xy=pdict_m4m5_thick[isar.name][pn], gridname=rg_m4m5_thick) pn = 'INM' + str(i) laygen.pin(name=pn, layer=laygen.layers['pin'][5], xy=pdict_m4m5_thick[isar.name][pn], gridname=rg_m4m5_thick) #clk output pins #laygen.add_pin('CLKBOUT_NC', 'CLKBOUT_NC', np.array([sar_xy, sar_xy])+sar_pins['CLKO07']['xy'], sar_pins['CLKO07']['layer']) laygen.add_pin('CLKOUT_DES', 'CLKOUT_DES', ret_pins['ck_out']['xy'], ret_pins['ck_out']['layer']) #retimer output pins for i in range(num_slices): for j in range(num_bits): pn = 'out_' + str(i) + '<' + str(j) + '>' pn_out = 'ADCOUT' + str(i) + '<' + str(j) + '>' xy = pdict_m3m4[iret.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][3], xy0=xy[0], xy1=xy[1], gridname0=rg_m3m4) laygen.boundary_pin_from_rect(r, rg_m3m4, pn_out, laygen.layers['pin'][3], size=4, direction='bottom') #extclk_sel pins for i in range(num_slices): pn = 'EXTSEL_CLK' + str(i) pn_out = 'EXTSEL_CLK' + str(i) xy = pdict_m5m6[isar.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][5], xy0=xy[0], xy1=xy[1], gridname0=rg_m5m6) laygen.boundary_pin_from_rect(r, rg_m5m6, pn_out, laygen.layers['pin'][5], size=4, direction='bottom') #asclkd pins for i in range(num_slices): for j in range(4): pn = 'ASCLKD' + str(i) + '<' + str(j) + '>' pn_out = 'ASCLKD' + str(i) + '<' + str(j) + '>' xy = pdict_m5m6[isar.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][5], xy0=xy[0], xy1=xy[1], gridname0=rg_m5m6) laygen.boundary_pin_from_rect(r, rg_m5m6, pn_out, laygen.layers['pin'][5], size=4, direction='bottom') # MODESEL pins if clkgen_mode == True: for i in range(num_slices): pn = 'MODESEL' + str(i) pn_out = 'MODESEL' + str(i) xy = pdict_m5m6[isar.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][5], xy0=xy[0], xy1=xy[1], gridname0=rg_m5m6) laygen.boundary_pin_from_rect(r, rg_m5m6, pn_out, laygen.layers['pin'][5], size=4, direction='bottom') #osp/osm pins if use_offset == True: for i in range(num_slices): laygen.pin(name='OSP' + str(i), layer=laygen.layers['pin'][4], xy=pdict_m4m5[isar.name]['OSP' + str(i)], gridname=rg_m4m5) laygen.pin(name='OSM' + str(i), layer=laygen.layers['pin'][4], xy=pdict_m4m5[isar.name]['OSM' + str(i)], gridname=rg_m4m5) #vref pins num_vref_routes = 4 for i in range(num_vref_routes): laygen.pin(name='VREF' + str(i) + '<0>', layer=laygen.layers['pin'][6], xy=pdict_m5m6_thick[isar.name]['VREF<0>_M6_' + str(i)], gridname=rg_m5m6_thick, netname='VREF<0>') laygen.pin(name='VREF' + str(i) + '<1>', layer=laygen.layers['pin'][6], xy=pdict_m5m6_thick[isar.name]['VREF<1>_M6_' + str(i)], gridname=rg_m5m6_thick, netname='VREF<1>') laygen.pin(name='VREF' + str(i) + '<2>', layer=laygen.layers['pin'][6], xy=pdict_m5m6_thick[isar.name]['VREF<2>_M6_' + str(i)], gridname=rg_m5m6_thick, netname='VREF<2>') #clkcal pins for i in range(num_slices): for j in range(clk_cdac_bits): pn = 'CLKCAL' + str(i) + '<' + str(j) + '>' pxy = clkdist_xy + clkdist_pins[pn]['xy'] laygen.add_pin(pn, pn, pxy, clkdist_pins[pn]['layer']) #clkin pins for i in range(clkin_trackm): pn = 'CLKIP' + '_' + str(i) nn = 'CLKIP' laygen.add_pin(pn, nn, clkdist_xy + clkdist_pins[pn]['xy'], clkdist_pins[pn]['layer']) pn = 'CLKIN' + '_' + str(i) nn = 'CLKIN' laygen.add_pin(pn, nn, clkdist_xy + clkdist_pins[pn]['xy'], clkdist_pins[pn]['layer']) laygen.add_pin('RSTP', 'RSTP', clkdist_xy + clkdist_pins['RSTP']['xy'], clkdist_pins['RSTP']['layer']) laygen.add_pin('RSTN', 'RSTN', clkdist_xy + clkdist_pins['RSTN']['xy'], clkdist_pins['RSTN']['layer']) # VREF SF pins if vref_sf == True: for pn, p in sar_pins.items(): if pn.startswith('VREF_SF_'): for i in range(num_slices): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, pn, pxy, sar_pins[pn]['layer']) # SF pins if use_sf == True: for pn, p in sar_pins.items(): if pn.startswith('SF_'): for i in range(num_slices): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, pn, pxy, sar_pins[pn]['layer']) #clkdist-sar routes (clock) #make virtual grids and route on the grids (assuming drc clearance of each block) # 1x pulsewidth rg_m4m5_temp = 'route_M4_M5_temp' laygenhelper.generate_grids_from_inst(laygen, gridname_input=rg_m4m5_basic_thick, gridname_output=rg_m4m5_temp, instname=isar.name, inst_pin_prefix=['CLK'], xy_grid_type='xgrid') pdict_m4m5_temp = laygen.get_inst_pin_xy(None, None, rg_m4m5_temp) # if clk_pulse == False: for i in range(num_slices): x0 = pdict_m4m5[isar.name]['CLK' + str(i)][0][0] y1 = pdict_m4m5[iclkdist.name]['CLKO' + str(i) + '<0>'][0][1] + 4 laygen.route_vh(layerv=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[iclkdist.name]['CLKO' + str(i) + '<0>'][0], xy1=np.array([x0, y1]), gridname0=rg_m4m5) # laygen.route_vh(layerv=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], # xy0=pdict_m4m5[iclkdist.name]['CLKO'+str(i)+'<1>'][0], # xy1=np.array([x0, y1+2]), gridname=rg_m4m5) # laygen.route_vh(layerv=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], # xy0=pdict_m4m5[iclkdist.name]['CLKO'+str(i)+'<0>'][0]+np.array([4,0]), # xy1=np.array([x0, y1+4]), gridname=rg_m4m5) # laygen.route_vh(layerv=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], # xy0=pdict_m4m5[iclkdist.name]['CLKO'+str(i)+'<1>'][0]+np.array([4,0]), # xy1=np.array([x0, y1+6]), gridname=rg_m4m5) laygen.route(None, layer=laygen.layers['metal'][5], xy0=pdict_m4m5_temp[isar.name]['CLK' + str(i)][0], xy1=np.array([ pdict_m4m5_temp[isar.name]['CLK' + str(i)][0][0], y1 + 0 ]), gridname0=rg_m4m5_temp) laygen.via( None, np.array([pdict_m4m5_temp[isar.name]['CLK' + str(i)][0][0], y1]), rg_m4m5_temp) # laygen.via(None,np.array([pdict_m4m5_temp[isar.name]['CLK'+str(i)][0][0], y1+2]), rg_m4m5_temp) # laygen.via(None,np.array([pdict_m4m5_temp[isar.name]['CLK'+str(i)][0][0], y1+4]), rg_m4m5_temp) # laygen.via(None,np.array([pdict_m4m5_temp[isar.name]['CLK'+str(i)][0][0], y1+6]), rg_m4m5_temp) # # clock routing for TISAR: 2x pulsewidth # elif clk_pulse == True: # for i in range(num_slices): # laygen.route_vhv(layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], # xy0=pdict_m4m5_basic_thick[isar.name]['CLK'+str(i)][0], # xy1=[pdict_m4m5[iclkdist.name]['CLKO%d<0>'%i][0][0]-3, pdict_m4m5[iclkdist.name]['DATAO<%d>'%i][0][1]-16], # track_y=pdict_m4m5[isar.name]['CLK'+str(i)][0][1]+3, # gridname0=rg_m4m5_basic_thick, layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5, extendl=0, extendr=0) # laygen.route_vhv(layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], # xy0=[pdict_m4m5[iclkdist.name]['CLKO%d<0>'%i][0][0]-3, pdict_m4m5[iclkdist.name]['DATAO<%d>'%i][0][1]-16], # xy1=pdict_m3m4[iclkdist.name]['DATAO<%d>'%i][0], # track_y=pdict_m4m5[iclkdist.name]['DATAO<%d>'%i][0][1]-14, # gridname0=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4, extendl=0, extendr=0) #sar-retimer routes (data) for i in range(num_slices): for j in range(num_bits): if ret_use_laygo == True: if j == num_bits - 1: laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0], xy1=pdict_m4m5[iret.name]['in_' + str(i) + '<' + str(j) + '>'][0], track_y=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0][1] + j * 2 + 2, gridname0=rg_m4m5, layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5, extendl=0, extendr=0) else: laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0], xy1=pdict_m3m4[iret.name]['in_' + str(i) + '<' + str(j) + '>'][0], track_y=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0][1] + j * 2 + 2, gridname0=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4, extendl=0, extendr=0) else: laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0], xy1=pdict_m3m4[iret.name]['in_' + str(i) + '<' + str(j) + '>'][0], track_y=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0][1] + j * 2 + 2, gridname0=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4, extendl=0, extendr=0) #sar-retimer routes (clock) #finding clock_bar phases <- added by Jaeduk #rules: # 1) last stage latches: num_slices-1 # 2) second last stage latches: int(num_slices/2)-1 # 3) the first half of first stage latches: int((int(num_slices/2)+1)%num_slices) # 4) the second half of first stage latches: 1 # 5) the output phase = the second last latch phase if num_slices > 4: ck_phase_2 = num_slices - 1 ck_phase_1 = int(num_slices / 2) - 1 ck_phase_0_0 = int((int(num_slices / 2) + 1) % num_slices) ck_phase_0_1 = 1 elif num_slices == 4: ck_phase_2 = 2 ck_phase_1 = 0 ck_phase_0_0 = 3 ck_phase_0_1 = 1 ck_phase_out = ck_phase_1 ck_phase_buf = sorted( set([ck_phase_2, ck_phase_1, ck_phase_0_0, ck_phase_0_1])) rg_m3m4_temp_clk = 'route_M3_M4_basic_temp_clk' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m3m4, gridname_output=rg_m3m4_temp_clk, instname=iret.name, inst_pin_prefix=['clk' + str(i) for i in ck_phase_buf], xy_grid_type='xgrid') pdict_m3m4_temp_clk = laygen.get_inst_pin_xy(None, None, rg_m3m4_temp_clk) for i in ck_phase_buf: for j in range(1): laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['CLKO0' + str(i)][0], xy1=pdict_m3m4_temp_clk[iret.name]['clk' + str(i)][0], track_y=pdict_m4m5[isar.name]['CLKO00'][0][1] + num_bits * 2 + 2 + 2 * j + 2 * (ck_phase_buf.index(i)), gridname0=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4_temp_clk, extendl=0, extendr=0) laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['CLKO1' + str(i)][0], xy1=pdict_m3m4_temp_clk[iret.name]['clk' + str(i)][0], track_y=pdict_m4m5[isar.name]['CLKO00'][0][1] + num_bits * 2 + 2 + 2 * j + 2 * (ck_phase_buf.index(i)), gridname0=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4_temp_clk, extendl=0, extendr=0) r = laygen.route( None, layer=laygen.layers['metal'][3], xy0=pdict_m3m4_temp_clk[iret.name]['clk' + str(i)][0], xy1=np.array([ pdict_m3m4_temp_clk[iret.name]['clk' + str(i)][0][0], pdict_m4m5[isar.name]['CLKO00'][0][1] + num_bits * 2 + 2 + 2 * 4 + 1 ]), gridname0=rg_m3m4_temp_clk)
def generate_sar_wsamp(laygen, objectname_pfix, workinglib, samp_lib, space_1x_lib, sar_name, samp_name, space_1x_name, placement_grid, routing_grid_m5m6, routing_grid_m3m4_basic_thick, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, num_inv_bb=0, num_bits=9, use_sf=False, vref_sf=False, origin=np.array([0, 0])): """generate sar with sampling frontend """ pg = placement_grid rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic #for clock routing # placement # sar isar = laygen.place(name="I" + objectname_pfix + 'SAR0', templatename=sar_name, gridname=pg, xy=origin, template_libname=workinglib) # samp isamp = laygen.relplace(name="I" + objectname_pfix + 'SAMP0', templatename=samp_name, gridname=pg, refinstname=isar.name, direction='top', template_libname=samp_lib) # source follower sf_name = 'sourceFollower_diff' if use_sf == True: isf = laygen.relplace(name="I" + objectname_pfix + 'SF0', templatename=sf_name, gridname=pg, refinstname=isamp.name, direction='top', template_libname=workinglib) sf_xy = isf.xy #prboundary sar_size = laygen.templates.get_template(sar_name, libname=workinglib).size samp_size = laygen.templates.get_template(samp_name, libname=samp_lib).size sf_size = laygen.templates.get_template(sf_name, libname=workinglib).size space_size = laygen.templates.get_template(space_1x_name, libname=space_1x_lib).size size_x = sar_size[0] size_y = int((sar_size[1] + samp_size[1]) / space_size[1] + 1) * space_size[1] if use_sf == True: size_y = int((sar_size[1] + samp_size[1] + sf_size[1]) / space_size[1] + 1) * space_size[1] laygen.add_rect(None, np.array([origin, origin + np.array([size_x, size_y])]), laygen.layers['prbnd']) # template handles sar_template = laygen.templates.get_template(sar_name, workinglib) samp_template = laygen.templates.get_template(samp_name, samp_lib) sf_template = laygen.templates.get_template(sf_name, workinglib) #reference coordinates pdict_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6) pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) pdict_m5m6_thick_basic = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_basic) sar_pins = sar_template.pins samp_pins = samp_template.pins sf_pins = sf_template.pins #sar_xy=isar.xy[0] #samp_xy=isamp.xy[0] sar_xy = isar.xy samp_xy = isamp.xy #signal route (clk/inp/inm) #make virtual grids and route on the grids (assuming drc clearance of each block) rg_m5m6_thick_basic_temp_sig = 'route_M5_M6_thick_basic_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick_basic, gridname_output=rg_m5m6_thick_basic_temp_sig, instname=isamp.name, inst_pin_prefix=['ckout'], xy_grid_type='xgrid') pdict_m5m6_thick_basic_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_basic_temp_sig) rg_m4m5_basic_thick_temp_sig = 'route_M4_M5_basic_thick_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m4m5_basic_thick, gridname_output=rg_m4m5_basic_thick_temp_sig, instname=isamp.name, inst_pin_prefix=['outp', 'outn'], xy_grid_type='xgrid') pdict_m4m5_basic_thick_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m4m5_basic_thick_temp_sig) #clock rclk0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['ckout'][0], xy1=pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1] - np.array([0, 1]), gridname0=rg_m5m6_thick_basic_temp_sig) laygen.via(None, pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1], rg_m5m6_thick_basic_temp_sig) laygen.via(None, pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK1'][1], rg_m5m6_thick_basic_temp_sig) #laygen.via(None,pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK2'][1], rg_m5m6_thick_basic_temp_sig) #rclk0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic[isamp.name]['ckout'][0], # xy1=pdict_m5m6_thick_basic[isar.name]['CLK'][1]-np.array([0,1]), gridname0=rg_m5m6_thick_basic) #laygen.via(None,pdict_m5m6_thick_basic[isar.name]['CLK'][1], rg_m5m6_thick_basic) #frontend sig inp_y_list = [] inm_y_list = [] for pn, p in pdict_m4m5_basic_thick_temp_sig[isar.name].items(): if pn.startswith('INP'): inp_y_list.append(p[0][1]) pv = np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0][0], p[0][1] ]) laygen.via(None, pv, rg_m4m5_basic_thick_temp_sig) #laygen.via(None,p[0], rg_m5m6_thick_basic_temp_sig) if pn.startswith('INM'): inm_y_list.append(p[0][1]) pv = np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0][0], p[0][1] ]) laygen.via(None, pv, rg_m4m5_basic_thick_temp_sig) #laygen.via(None,p[0], rg_m5m6_thick_basic_temp_sig) inp_y = min(inp_y_list) inm_y = min(inm_y_list) rinp0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0], xy1=np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0][0], inp_y - 1 ]), gridname0=rg_m4m5_basic_thick_temp_sig) rinm0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0], xy1=np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0][0], inm_y - 1 ]), gridname0=rg_m4m5_basic_thick_temp_sig) #rinp0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INP0'][0][0],inp_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) #rinm0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INM0'][0][0],inm_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) # source follower routing pdict_m4m5_thick = laygen.get_inst_pin_xy(None, None, rg_m4m5_thick) if use_sf == True: [rh0, rv0] = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5_thick[isf.name]['outp'][0], pdict_m4m5_thick[isamp.name]['inp'][0], rg_m4m5_thick) [rh0, rv0] = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5_thick[isf.name]['outn'][0], pdict_m4m5_thick[isamp.name]['inn'][0], rg_m4m5_thick) # VDD/VSS for source follower for pn, p in samp_pins.items(): if pn.startswith('LVDD'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD1'][0], rg_m4m5_thick) if pn.startswith('RVDD'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD1'][0], rg_m4m5_thick) if pn.startswith('LVSS'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS1'][0], rg_m4m5_thick) if pn.startswith('RVSS'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS1'][0], rg_m4m5_thick) #input pins (just duplicate from lower hierarchy cells) laygen.add_pin('CLK', 'CLK', samp_xy + samp_pins['ckin']['xy'], samp_pins['ckin']['layer']) if use_sf == False: laygen.add_pin('INP', 'INP', samp_xy + samp_pins['inp']['xy'], samp_pins['inp']['layer']) laygen.add_pin('INM', 'INM', samp_xy + samp_pins['inn']['xy'], samp_pins['inn']['layer']) else: laygen.add_pin('INP', 'INP', sf_xy + sf_pins['inp']['xy'], sf_pins['inp']['layer']) laygen.add_pin('INM', 'INM', sf_xy + sf_pins['inn']['xy'], sf_pins['inn']['layer']) for pn, p in sf_pins.items(): if pn.startswith('Voffp'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_' + pn, 'SF_Voffp', pxy, sf_pins[pn]['layer']) if pn.startswith('Voffn'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_' + pn, 'SF_Voffn', pxy, sf_pins[pn]['layer']) if pn.startswith('bypass'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_' + pn, 'SF_bypass', pxy, sf_pins[pn]['layer']) if pn.startswith('VBIAS'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_BIAS', 'SF_BIAS', pxy, sf_pins[pn]['layer']) # if pn.startswith('VBIASn'): # pxy = sf_xy + sf_pins[pn]['xy'] # laygen.add_pin('SF_BIASn', 'SF_BIASn', pxy, sf_pins[pn]['layer']) if vref_sf == True: laygen.add_pin('VREF_SF_BIAS', 'VREF_SF_BIAS', sar_xy + sar_pins['SF_VBIAS']['xy'], sar_pins['SF_VBIAS']['layer']) laygen.add_pin('VREF_SF_bypass', 'VREF_SF_bypass', sar_xy + sar_pins['SF_bypass']['xy'], sar_pins['SF_bypass']['layer']) laygen.add_pin('OSP', 'OSP', sar_xy + sar_pins['OSP']['xy'], sar_pins['OSP']['layer']) laygen.add_pin('OSM', 'OSM', sar_xy + sar_pins['OSM']['xy'], sar_pins['OSM']['layer']) for pn, p in sar_pins.items(): if pn.startswith('VREF<0>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<0>', pxy, sar_pins[pn]['layer']) if pn.startswith('VREF<1>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<1>', pxy, sar_pins[pn]['layer']) if pn.startswith('VREF<2>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<2>', pxy, sar_pins[pn]['layer']) #laygen.add_pin('VREF_M5R<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5R<2>']['xy'], sar_pins['VREF_M5R<2>']['layer']) #laygen.add_pin('VREF_M5R<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5R<1>']['xy'], sar_pins['VREF_M5R<1>']['layer']) #laygen.add_pin('VREF_M5R<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5R<0>']['xy'], sar_pins['VREF_M5R<0>']['layer']) #laygen.add_pin('VREF_M5L<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5L<2>']['xy'], sar_pins['VREF_M5L<2>']['layer']) #laygen.add_pin('VREF_M5L<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5L<1>']['xy'], sar_pins['VREF_M5L<1>']['layer']) #laygen.add_pin('VREF_M5L<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5L<0>']['xy'], sar_pins['VREF_M5L<0>']['layer']) laygen.add_pin('CKDSEL0<1>', 'CKDSEL0<1>', sar_xy + sar_pins['CKDSEL0<1>']['xy'], sar_pins['CKDSEL0<1>']['layer']) laygen.add_pin('CKDSEL0<0>', 'CKDSEL0<0>', sar_xy + sar_pins['CKDSEL0<0>']['xy'], sar_pins['CKDSEL0<0>']['layer']) laygen.add_pin('CKDSEL1<1>', 'CKDSEL1<1>', sar_xy + sar_pins['CKDSEL1<1>']['xy'], sar_pins['CKDSEL1<1>']['layer']) laygen.add_pin('CKDSEL1<0>', 'CKDSEL1<0>', sar_xy + sar_pins['CKDSEL1<0>']['xy'], sar_pins['CKDSEL1<0>']['layer']) #laygen.add_pin('EXTCLK', 'EXTCLK', sar_xy+sar_pins['EXTCLK']['xy'], sar_pins['EXTCLK']['layer']) laygen.add_pin('EXTSEL_CLK', 'EXTSEL_CLK', sar_xy + sar_pins['EXTSEL_CLK']['xy'], sar_pins['EXTSEL_CLK']['layer']) #output pins (just duplicate from lower hierarchy cells) for i in range(num_bits): pn = 'ADCOUT' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) laygen.add_pin('CLKO0', 'CLKO', sar_xy + sar_pins['CLKOUT0']['xy'], sar_pins['CLKOUT0']['layer']) laygen.add_pin('CLKO1', 'CLKO', sar_xy + sar_pins['CLKOUT1']['xy'], sar_pins['CLKOUT1']['layer']) #laygen.add_pin('CLKO2', 'CLKO', sar_xy+sar_pins['CLKOUT2']['xy'], sar_pins['CLKOUT2']['layer']) #probe pins laygen.add_pin('CLK0', 'ICLK', sar_xy + sar_pins['CLK0']['xy'], sar_pins['CLK0']['layer']) laygen.add_pin('CLK1', 'ICLK', sar_xy + sar_pins['CLK1']['xy'], sar_pins['CLK1']['layer']) #laygen.add_pin('CLK2', 'ICLK', sar_xy+sar_pins['CLK2']['xy'], sar_pins['CLK2']['layer']) laygen.add_pin('CLKPRB_SAMP', 'CLKPRB_SAMP', samp_xy + samp_pins['ckpg']['xy'], samp_pins['ckpg']['layer']) #laygen.add_pin('CLKPRB_SAR', 'CLKPRB_SAR', sar_xy+sar_pins['CLKPRB']['xy'], sar_pins['CLKPRB']['layer']) laygen.add_pin('SAMPP', 'SAMPP', sar_xy + sar_pins['SAINP']['xy'], sar_pins['SAINP']['layer']) laygen.add_pin('SAMPM', 'SAMPM', sar_xy + sar_pins['SAINM']['xy'], sar_pins['SAINM']['layer']) laygen.add_pin('SAOP', 'SAOP', sar_xy + sar_pins['SAOP']['xy'], sar_pins['SAOP']['layer']) laygen.add_pin('SAOM', 'SAOM', sar_xy + sar_pins['SAOM']['xy'], sar_pins['SAOM']['layer']) laygen.add_pin('SARCLK', 'SARCLK', sar_xy + sar_pins['SARCLK']['xy'], sar_pins['SARCLK']['layer']) laygen.add_pin('SARCLKB', 'SARCLKB', sar_xy + sar_pins['SARCLKB']['xy'], sar_pins['SARCLKB']['layer']) #laygen.add_pin('COMPOUT', 'COMPOUT', sar_xy+sar_pins['COMPOUT']['xy'], sar_pins['COMPOUT']['layer']) laygen.add_pin('DONE', 'DONE', sar_xy + sar_pins['DONE']['xy'], sar_pins['DONE']['layer']) laygen.add_pin('UP', 'UP', sar_xy + sar_pins['UP']['xy'], sar_pins['UP']['layer']) laygen.add_pin('PHI0', 'PHI0', sar_xy + sar_pins['PHI0']['xy'], sar_pins['PHI0']['layer']) for i in range(num_bits): pn = 'ZP' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'ZMID' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'ZM' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'SB' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) for i in range(num_bits - 1): pn = 'VOL' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'VOR' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) #VDD/VSS pin vddcnt = 0 vsscnt = 0 for p in pdict_m5m6[isar.name]: if p.startswith('VDD'): xy0 = pdict_m5m6_thick[isar.name][p] laygen.pin(name='VDDSAR' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDDSAR') vddcnt += 1 if p.startswith('VSS'): xy0 = pdict_m5m6_thick[isar.name][p] laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS:') #laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS') vsscnt += 1 #extract VDD/VSS grid from samp and make power pins rg_m5m6_thick_temp_samp = 'route_M5_M6_thick_temp_samp' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_samp, instname=isamp.name, inst_pin_prefix=['VDD', 'VSS', 'samp_body'], xy_grid_type='ygrid') pdict_m5m6_thick_temp_samp = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_temp_samp) vddcnt = 0 vsscnt = 0 bodycnt = 0 for p in pdict_m5m6_thick_temp_samp[isamp.name]: if p.startswith('VDD'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='VDDSAMP' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VDDSAMP') vddcnt += 1 if p.startswith('VSS'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS:') #laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS') vsscnt += 1 if p.startswith('samp_body'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='samp_body', layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='samp_body') bodycnt += 1 # VBB pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4_basic_thick) if not num_inv_bb == 0: rvbb_m3 = [] for p in pdict_m3m4[isar.name]: if p.startswith('VBB') and p.endswith('0'): rvbb_m3.append(pdict_m3m4[isar.name][p]) # laygen.pin(name='bottom_body'+str(p), layer=laygen.layers['pin'][3], xy=pdict_m3m4[isar.name][p], gridname=rg_m3m4, netname='bottom_body') rvbb_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_basic_thick, netnames=['bottom_body'], direction='x', input_rails_xy=[rvbb_m3], generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rvbb_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['bottom_body'], direction='y', input_rails_rect=rvbb_m4, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-2) rvbb_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['bottom_body'], direction='x', input_rails_rect=rvbb_m5, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) num_m6 = len(rvbb_m6[0]) for i in range(num_m6): if i % 2 == 1: rvbb_m6[0].remove(rvbb_m6[0][num_m6 - i - 1]) print(rvbb_m6[0]) rvbb_m7 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M7_', layer=laygen.layers['pin'][7], gridname=rg_m6m7_thick, netnames=['bottom_body'], direction='y', input_rails_rect=rvbb_m6, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0)
def generate_tisaradc_body(laygen, objectname_pfix, libname, tisar_core_name, tisar_space_name, tisar_space2_name, placement_grid, routing_grid_m3m4, routing_grid_m4m5, routing_grid_m4m5_basic_thick, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, routing_grid_m6m7_thick, routing_grid_m7m8_thick, num_bits=9, num_slices=8, origin=np.array([0, 0])): """generate sar array """ pg = placement_grid rg_m3m4 = routing_grid_m3m4 rg_m4m5 = routing_grid_m4m5 rg_m4m5 = routing_grid_m4m5 rg_m4m5_basic_thick = routing_grid_m4m5_basic_thick rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic rg_m6m7_thick = routing_grid_m6m7_thick rg_m7m8_thick = routing_grid_m7m8_thick # placement ispace20 = laygen.place(name="I" + objectname_pfix + 'SP20', templatename=tisar_space2_name, gridname=pg, xy=origin, template_libname=libname) space20_template = laygen.templates.get_template(tisar_space2_name, libname) space20_pins = space20_template.pins space20_xy = ispace20.xy space0_origin = laygen.get_xy(obj=ispace20.template, gridname=pg) * np.array([1, 0]) ispace0 = laygen.place(name="I" + objectname_pfix + 'SP0', templatename=tisar_space_name, gridname=pg, xy=space0_origin, template_libname=libname) space_template = laygen.templates.get_template(tisar_space_name, libname) space_pins = space_template.pins space0_xy = ispace0.xy sar_origin = space0_origin + laygen.get_xy(obj=ispace0.template, gridname=pg) * np.array([1, 0]) isar = laygen.place(name="I" + objectname_pfix + 'SAR0', templatename=tisar_core_name, gridname=pg, xy=sar_origin, template_libname=libname) sar_template = laygen.templates.get_template(tisar_core_name, libname) sar_pins = sar_template.pins sar_xy = isar.xy space1_origin = sar_origin + laygen.get_xy(obj=isar.template, gridname=pg) * np.array([1, 0]) ispace1 = laygen.place(name="I" + objectname_pfix + 'SP1', templatename=tisar_space_name, gridname=pg, xy=space1_origin, template_libname=libname) space1_xy = ispace1.xy space21_origin = space1_origin + laygen.get_xy( obj=ispace1.template, gridname=pg) * np.array([1, 0]) ispace21 = laygen.place(name="I" + objectname_pfix + 'SP21', templatename=tisar_space2_name, gridname=pg, xy=space21_origin, template_libname=libname) space21_xy = ispace21.xy #prboundary sar_size = laygen.templates.get_template(tisar_core_name, libname=libname).size space_size = laygen.templates.get_template(tisar_space_name, libname=libname).size space2_size = laygen.templates.get_template(tisar_space2_name, libname=libname).size #VDD/VSS/VREF integration rvddclkd = [] rvddsamp = [] rvddsar = [] rvddsar_upper = [] rvref0 = [] rvref1 = [] rvref2 = [] rvssclkd = [] rvsssamp = [] rvsssar = [] rvsssar_upper = [] vddsampcnt = 0 vddsarcnt = 0 y_vddsar_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 fiugre out htresholds for pn, p in sar_pins.items(): if pn.startswith('VDDCLKD'): pxy = np.array([[0, space0_xy[1] + sar_pins[pn]['xy'][0][1]], [ space_size[0] * 4 + sar_size[0], space1_xy[1] + 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] if pn.startswith('VDDSAMP'): pxy = np.array([[0, space0_xy[1] + sar_pins[pn]['xy'][0][1]], [ space_size[0] * 4 + sar_size[0], space1_xy[1] + 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] if pn.startswith('VDDSAR'): pxy = np.array([[0, space0_xy[1] + sar_pins[pn]['xy'][0][1]], [ space_size[0] * 4 + sar_size[0], space1_xy[1] + sar_pins[pn]['xy'][1][1] ]]) if pxy[0][1] > y_vref0: rvddsar_upper.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) else: rvddsar.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pxy[1][1] > y_vddsar_max: y_vddsar_max = pxy[1][1] if pn.startswith('VREF'): pxy = np.array([[0, space0_xy[1] + sar_pins[pn]['xy'][0][1]], [ space_size[0] * 4 + sar_size[0], space1_xy[1] + 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 y_vss_th2 = 0.5 * (y_vddsamp_max + y_vddclkd_min) #find out threshold for pn, p in sar_pins.items(): if pn.startswith('VSS'): pxy = np.array([[0, space0_xy[1] + sar_pins[pn]['xy'][0][1]], [ space_size[0] * 4 + sar_size[0], space1_xy[1] + sar_pins[pn]['xy'][1][1] ]]) if pxy[0][1] > y_vss_th2: rvssclkd.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) elif pxy[0][1] > y_vss_th: rvsssamp.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) elif pxy[0][1] > y_vref0: rvsssar_upper.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) else: rvsssar.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) # for i in range(len(rvddsar)): # print(rvddsar[i].xy) #M7 rails rg_route = 'route_M6_M7_thick_temp_pwr' if input_htree == False: laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m6m7_thick, gridname_output=rg_route, instname=[isar.name], inst_pin_prefix=['VDD', 'VSS', 'VREF'], xy_grid_type='ygrid') rg_route_m7m8 = 'route_M7_M8_thick' else: x_ref = laygen.templates.get_template('sar_wsamp', libname=workinglib).size[0] x_pitch = laygen.get_grid(rg_m6m7_thick).xy[1][0] xy = np.array([[0, 0], [x_ref, laygen.get_grid(rg_m6m7_thick).xy[1][1]]]) ywidth = np.array(laygen.get_grid(rg_m6m7_thick).ywidth) # xgrid = np.array([x_pitch, x_ref]) xgrid = np.array( [x_pitch, 2 * x_pitch, x_ref - 1 * x_pitch, x_ref - 0 * x_pitch]) ygrid = np.array([0]) vianame = list(laygen.get_grid(rg_m6m7_thick).viamap.keys())[0] viamap = {vianame: []} for x in range(len(xgrid)): viamap[vianame].append([x, 0]) xwidth = np.repeat(laygen.get_grid(rg_m6m7_thick).xwidth, len(xgrid)) viamap[vianame] = np.array(viamap[vianame]) laygen.grids.add_route_grid(name=rg_route, xy=xy, xgrid=xgrid, ygrid=ygrid, xwidth=xwidth, ywidth=ywidth, viamap=viamap) rg_route_m7m8 = 'route_M7_M8_thick_temp_pwr' xy = np.array([[0, 0], [ laygen.get_grid(rg_route).xy[1][0], laygen.get_grid(rg_m7m8_thick).xy[1][1] ]]) ywidth = np.array(laygen.get_grid(rg_m7m8_thick).ywidth) xgrid = laygen.get_grid(rg_route).xgrid ygrid = laygen.get_grid(rg_route).ygrid vianame = list(laygen.get_grid(rg_m7m8_thick).viamap.keys())[0] viamap = {vianame: []} for x in range(len(xgrid)): viamap[vianame].append([x, 0]) xwidth = np.repeat(laygen.get_grid(rg_m7m8_thick).xwidth, len(xgrid)) viamap[vianame] = np.array(viamap[vianame]) laygen.grids.add_route_grid(name=rg_route_m7m8, xy=xy, xgrid=xgrid, ygrid=ygrid, xwidth=xwidth, ywidth=ywidth, viamap=viamap) laygen.grids.display(libname=None, gridname=rg_route) laygen.grids.display(libname=None, gridname=rg_route_m7m8) ''' #M7 rails-clkd input_rails_rect = [rvddclkd, rvssclkd] rvddclkd_m7_pre, rvssclkd_m7_pre= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDCLKD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, offset_end_coord=None, offset_start_index=2, offset_end_index=-2) ''' #M7 rails-samp input_rails_rect = [rvddsamp, rvsssamp] rvddsamp_m7_pre, rvsssamp_m7_pre = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAMP_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDSAMP', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, offset_end_coord=None, offset_start_index=1, offset_end_index=-1) #M7 rails-sar_lower input_rails_rect = [rvddsar, rvsssar] rvddsar_m7, rvsssar_m7 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAR_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDSAR', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=-1) #M7 rails-sar_upper(+vref) input_rails_rect = [ rvddsar_upper, rvsssar_upper, rvref0, rvsssar_upper, rvref1, rvsssar_upper, rvref2, rvsssar_upper ] rvddsar_m7_upper, rvsssar0_m7, rvref0_m7_pre, rvsssar1_m7, rvref1_m7_pre, rvsssar2_m7, rvref2_m7_pre, rvsssar3_m7 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAR_UPPER_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=[ 'VDDSAR', 'VSS', 'VREF<0>', 'VSS', 'VREF<1>', 'VSS', 'VREF<2>', 'VSS' ], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=-1) rvsssar_m7_upper_pre = rvsssar0_m7 + rvsssar1_m7 + rvsssar2_m7 + rvsssar3_m7 #extend m7 rails for clkd and samp and vref, rvsssar_m7_upper #rvddclkd_m7=[] #rvssclkd_m7=[] rvddsamp_m7 = [] rvsssamp_m7 = [] rvref0_m7 = [] rvref1_m7 = [] rvref2_m7 = [] rvsssar_m7_upper = [] ''' for r in rvddclkd_m7_pre: rxy=laygen.get_xy(obj = r, gridname=rg_m6m7_thick, sort=True) rxy[1][1]+=12 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvddclkd_m7.append(r2) for r in rvssclkd_m7_pre: rxy=laygen.get_xy(obj = r, gridname=rg_m6m7_thick, sort=True) rxy[1][1]+=12 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvssclkd_m7.append(r2) ''' for r in rvddsamp_m7_pre: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) #rxy[0][1]-=1 rxy[1][1] += 24 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) rvddsamp_m7.append(r2) for r in rvsssamp_m7_pre: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) #rxy[0][1]-=1 rxy[1][1] += 24 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) rvsssamp_m7.append(r2) #extend upper vss routes in the space area down to zero (for vss short) if r.xy[0][0] < sar_xy[0]: laygen.route(None, laygen.layers['metal'][7], xy0=[rxy[0][0], 0], xy1=rxy[1], gridname0=rg_route) if r.xy[0][0] > sar_xy[0] + sar_template.width: laygen.route(None, laygen.layers['metal'][7], xy0=[rxy[0][0], 0], xy1=rxy[1], gridname0=rg_route) for r in rvref0_m7_pre: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) # rxy[0][1]-=24 #rxy[1][1]+=24 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) print(r2.xy) rvref0_m7.append(r2) for r in rvref1_m7_pre: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) # rxy[0][1]-=24 #rxy[1][1]+=24 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) rvref1_m7.append(r2) for r in rvref2_m7_pre: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) # rxy[0][1]-=24 #rxy[1][1]+=24 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) rvref2_m7.append(r2) for r in rvsssar_m7_upper_pre: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) # rxy[0][1]-=24 #rxy[1][1]+=24 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) rvsssar_m7_upper.append(r2) #connect VDDSAR/VSS in sar region for r in rvddsar_m7_upper: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) rxy[0][1] = 1 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) for r in rvsssar_m7_upper: rxy = laygen.get_xy(obj=r, gridname=rg_route, sort=True) rxy[0][1] = 1 r2 = laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_route) #connect VSS between sar/samp/clkd in space region ''' for r in rvssclkd_m7: if r.xy[1][0] < sar_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvsssar_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) if r.xy[0][0] > space1_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvsssar_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) ''' #create VSS pins for connection to core for i, r in enumerate(rvsssar_m7): pxy = np.array([[r.xy[0][0], 0], r.xy[1]]) laygen.add_rect(None, pxy, laygen.layers['metal'][7]) # laygen.add_pin('VSS_SAR_M7_'+str(i), 'VSS', pxy, laygen.layers['pin'][7]) ''' #connect VDDSAMP between samp/clkd in space region for r in rvddclkd_m7: if r.xy[1][0] < sar_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvddsamp_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) if r.xy[0][0] > space1_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvddsamp_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) #M8 routes #input_rails_rect = [rvddclkd_m7, rvssclkd_m7] #rvddclkd_m8, rvssclkd_m8= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_M8_', # layer=laygen.layers['pin'][8], gridname=rg_m7m8_thick, 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=1, offset_end_index=0) input_rails_rect = [rvssclkd_m7, rvddclkd_m7] rvssclkd_m8, rvddclkd_m8= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_M8_', layer=laygen.layers['pin'][8], gridname=rg_m7m8_thick, netnames=['VSS', 'VDDSAMP'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) ''' #M8 routes input_rails_rect = [rvsssamp_m7, rvddsamp_m7] rvsssamp_m8, rvddsamp_m8 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAMP_M8_', layer=laygen.layers['pin'][8], gridname=rg_route_m7m8, netnames=['VSS', 'VDDSAMP'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) input_rails_rect = [rvddsar_m7, rvsssar_m7] rvddsar_m8, rvsssar_m8 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAR_M8_', layer=laygen.layers['pin'][8], gridname=rg_route_m7m8, netnames=['VDDSAR', '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) input_rails_rect = [ rvref0_m7, rvsssar_m7_upper, rvref1_m7, rvsssar_m7_upper, rvref2_m7, rvsssar_m7_upper ] laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_VREF_M8_', layer=laygen.layers['metal'][8], gridname=rg_route_m7m8, netnames=['VREF<0>', 'VSS', 'VREF<1>', 'VSS', 'VREF<2>', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) #osp/osm route if use_offset == True: # To be done pdict_os_m4m5 = laygen.get_inst_pin_xy(None, None, rg_m4m5) rosp_m5 = [] rosm_m5 = [] for i in range(num_slices): rh0, rv0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_os_m4m5[isar.name]['OSP' + str(i)][0], pdict_os_m4m5[isar.name]['OSP' + str(i)][0] + np.array([-2 * i - 2, -10]), gridname0=rg_m4m5) rosp_m5.append(rv0) rh0, rv0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_os_m4m5[isar.name]['OSM' + str(i)][0], pdict_os_m4m5[isar.name]['OSM' + str(i)][0] + np.array([-2 * num_slices - 2 * i - 2, -10]), gridname0=rg_m4m5) rosm_m5.append(rv0) pdict_os_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6) x0 = pdict_os_m5m6[isar.name]['VREF0<0>'][0][0] - 4 * num_slices y0 = pdict_os_m5m6[isar.name]['VREF0<0>'][0][1] - 8 rosp_m6 = [] rosm_m6 = [] for i in range(num_slices): xy0 = laygen.get_xy(obj=rosp_m5[i], gridname=rg_m5m6, sort=True)[0] rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0, np.array([x0, y0 - 2 * i]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rh0, rg_m5m6, 'OSP' + str(i), laygen.layers['pin'][6], size=6, direction='left') rosp_m6.append(rh0) xy0 = laygen.get_xy(obj=rosm_m5[i], gridname=rg_m5m6, sort=True)[0] rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0, np.array([x0, y0 - 2 * i - 1]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rh0, rg_m5m6, 'OSM' + str(i), laygen.layers['pin'][6], size=6, direction='left') rosm_m6.append(rh0) # pdict_os_m4m5 = laygen.get_inst_pin_xy(None, None, rg_m4m5_basic_thick) # rosp_m5=[] # rosm_m5=[] # for i in range(num_slices): # rh0, rv0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_os_m4m5[isar.name]['OSP'+str(i)][0], pdict_os_m4m5[isar.name]['OSP'+str(i)][0]+np.array([-i-2, -10]), gridname=rg_m4m5_basic_thick) # rosp_m5.append(rv0) # rh0, rv0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_os_m4m5[isar.name]['OSM'+str(i)][0], pdict_os_m4m5[isar.name]['OSM'+str(i)][0]+np.array([-num_slices-i-2, -10]), gridname=rg_m4m5_basic_thick) # rosm_m5.append(rv0) # pdict_os_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) # x0=pdict_os_m5m6[isar.name]['VREF0<0>'][0][0]-4*num_slices # y0=pdict_os_m5m6[isar.name]['VREF0<0>'][0][1]-8 # rosp_m6=[] # rosm_m6=[] # for i in range(num_slices): # xy0=laygen.get_xy(obj = rosp_m5[i], gridname=rg_m5m6_thick, sort=True)[0] # rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0, np.array([x0, y0-2*i]), gridname=rg_m5m6_thick) # laygen.boundary_pin_from_rect(rh0, rg_m5m6_thick, 'OSP' + str(i), laygen.layers['pin'][6], size=6, # direction='left') # rosp_m6.append(rh0) # xy0=laygen.get_xy(obj = rosm_m5[i], gridname=rg_m5m6_thick, sort=True)[0] # rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0, np.array([x0, y0-2*i-1]), gridname=rg_m5m6_thick) # laygen.boundary_pin_from_rect(rh0, rg_m5m6_thick, 'OSM' + str(i), laygen.layers['pin'][6], size=6, # direction='left') # rosm_m6.append(rh0) #other pins - duplicate pin_prefix_list = [ 'INP', 'INM', 'VREF', 'ASCLKD', 'EXTSEL_CLK', 'ADCOUT', 'CLKOUT_DES', 'CLKCAL', 'RSTP', 'RSTN', 'CLKIP', 'CLKIN', 'SF_', 'VREF_SF_', 'MODESEL' ] if use_sf == False: pin_prefix_list.remove('SF_') if vref_sf == False: pin_prefix_list.remove('VREF_SF_') if clkgen_mode == False: pin_prefix_list.remove('MODESEL') for pn, p in sar_pins.items(): for pfix in pin_prefix_list: if pn.startswith(pfix): laygen.add_pin(pn, sar_pins[pn]['netname'], sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) bndvss = rvsssamp_m7[-1].get_xy()[1] bndvdd = rvddsamp_m7[-1].get_xy()[1] xbnd = space_size * 2 + space2_size * 2 + sar_size bnd = (xbnd[0], max([bndvdd[1], bndvss[1]])) laygen.add_rect(None, np.array([origin, bnd]), laygen.layers['prbnd'])
def generate_sar_wsamp(laygen, objectname_pfix, workinglib, samp_lib, space_1x_lib, sar_name, samp_name, space_1x_name, placement_grid, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, num_bits=9, origin=np.array([0, 0])): """generate sar with sampling frontend """ pg = placement_grid rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic #for clock routing # placement # sar isar = laygen.place(name="I" + objectname_pfix + 'SAR0', templatename=sar_name, gridname=pg, xy=origin, template_libname=workinglib) # samp isamp = laygen.relplace(name="I" + objectname_pfix + 'SAMP0', templatename=samp_name, gridname=pg, refinstname=isar.name, direction='top', template_libname=samp_lib) #prboundary sar_size = laygen.templates.get_template(sar_name, libname=workinglib).size samp_size = laygen.templates.get_template(samp_name, libname=samp_lib).size space_size = laygen.templates.get_template(space_1x_name, libname=space_1x_lib).size size_x = sar_size[0] size_y = int((sar_size[1] + samp_size[1]) / space_size[1] + 1) * space_size[1] laygen.add_rect(None, np.array([origin, origin + np.array([size_x, size_y])]), laygen.layers['prbnd']) # template handles sar_template = laygen.templates.get_template(sar_name, workinglib) samp_template = laygen.templates.get_template(samp_name, samp_lib) #reference coordinates pdict_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6) pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) pdict_m5m6_thick_basic = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_basic) sar_pins = sar_template.pins samp_pins = samp_template.pins #sar_xy=isar.xy[0] #samp_xy=isamp.xy[0] sar_xy = isar.xy samp_xy = isamp.xy #signal route (clk/inp/inm) #make virtual grids and route on the grids (assuming drc clearance of each block) rg_m5m6_thick_basic_temp_sig = 'route_M5_M6_thick_basic_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick_basic, gridname_output=rg_m5m6_thick_basic_temp_sig, instname=isamp.name, inst_pin_prefix=['ckout'], xy_grid_type='xgrid') pdict_m5m6_thick_basic_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_basic_temp_sig) rg_m4m5_basic_thick_temp_sig = 'route_M4_M5_basic_thick_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m4m5_basic_thick, gridname_output=rg_m4m5_basic_thick_temp_sig, instname=isamp.name, inst_pin_prefix=['outp', 'outn'], xy_grid_type='xgrid') pdict_m4m5_basic_thick_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m4m5_basic_thick_temp_sig) #clock rclk0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['ckout'][0], xy1=pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1] - np.array([0, 1]), gridname0=rg_m5m6_thick_basic_temp_sig) laygen.via(None, pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1], rg_m5m6_thick_basic_temp_sig) laygen.via(None, pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK1'][1], rg_m5m6_thick_basic_temp_sig) #laygen.via(None,pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK2'][1], rg_m5m6_thick_basic_temp_sig) #rclk0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic[isamp.name]['ckout'][0], # xy1=pdict_m5m6_thick_basic[isar.name]['CLK'][1]-np.array([0,1]), gridname0=rg_m5m6_thick_basic) #laygen.via(None,pdict_m5m6_thick_basic[isar.name]['CLK'][1], rg_m5m6_thick_basic) #frontend sig inp_y_list = [] inm_y_list = [] for pn, p in pdict_m4m5_basic_thick_temp_sig[isar.name].items(): if pn.startswith('INP'): inp_y_list.append(p[0][1]) pv = np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0][0], p[0][1] ]) laygen.via(None, pv, rg_m4m5_basic_thick_temp_sig) #laygen.via(None,p[0], rg_m5m6_thick_basic_temp_sig) if pn.startswith('INM'): inm_y_list.append(p[0][1]) pv = np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0][0], p[0][1] ]) laygen.via(None, pv, rg_m4m5_basic_thick_temp_sig) #laygen.via(None,p[0], rg_m5m6_thick_basic_temp_sig) inp_y = min(inp_y_list) inm_y = min(inm_y_list) rinp0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0], xy1=np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0][0], inp_y - 1 ]), gridname0=rg_m4m5_basic_thick_temp_sig) rinm0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0], xy1=np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0][0], inm_y - 1 ]), gridname0=rg_m4m5_basic_thick_temp_sig) #rinp0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INP0'][0][0],inp_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) #rinm0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INM0'][0][0],inm_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) #input pins (just duplicate from lower hierarchy cells) laygen.add_pin('CLK', 'CLK', samp_xy + samp_pins['ckin']['xy'], samp_pins['ckin']['layer']) laygen.add_pin('INP', 'INP', samp_xy + samp_pins['inp']['xy'], samp_pins['ckin']['layer']) laygen.add_pin('INM', 'INM', samp_xy + samp_pins['inn']['xy'], samp_pins['ckin']['layer']) laygen.add_pin('OSP', 'OSP', sar_xy + sar_pins['OSP']['xy'], sar_pins['OSP']['layer']) laygen.add_pin('OSM', 'OSM', sar_xy + sar_pins['OSM']['xy'], sar_pins['OSM']['layer']) for pn, p in sar_pins.items(): if pn.startswith('VREF<0>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<0>', pxy, sar_pins[pn]['layer']) if pn.startswith('VREF<1>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<1>', pxy, sar_pins[pn]['layer']) if pn.startswith('VREF<2>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<2>', pxy, sar_pins[pn]['layer']) #laygen.add_pin('VREF_M5R<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5R<2>']['xy'], sar_pins['VREF_M5R<2>']['layer']) #laygen.add_pin('VREF_M5R<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5R<1>']['xy'], sar_pins['VREF_M5R<1>']['layer']) #laygen.add_pin('VREF_M5R<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5R<0>']['xy'], sar_pins['VREF_M5R<0>']['layer']) #laygen.add_pin('VREF_M5L<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5L<2>']['xy'], sar_pins['VREF_M5L<2>']['layer']) #laygen.add_pin('VREF_M5L<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5L<1>']['xy'], sar_pins['VREF_M5L<1>']['layer']) #laygen.add_pin('VREF_M5L<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5L<0>']['xy'], sar_pins['VREF_M5L<0>']['layer']) laygen.add_pin('CKDSEL0<1>', 'CKDSEL0<1>', sar_xy + sar_pins['CKDSEL0<1>']['xy'], sar_pins['CKDSEL0<1>']['layer']) laygen.add_pin('CKDSEL0<0>', 'CKDSEL0<0>', sar_xy + sar_pins['CKDSEL0<0>']['xy'], sar_pins['CKDSEL0<0>']['layer']) laygen.add_pin('CKDSEL1<1>', 'CKDSEL1<1>', sar_xy + sar_pins['CKDSEL1<1>']['xy'], sar_pins['CKDSEL1<1>']['layer']) laygen.add_pin('CKDSEL1<0>', 'CKDSEL1<0>', sar_xy + sar_pins['CKDSEL1<0>']['xy'], sar_pins['CKDSEL1<0>']['layer']) #laygen.add_pin('EXTCLK', 'EXTCLK', sar_xy+sar_pins['EXTCLK']['xy'], sar_pins['EXTCLK']['layer']) laygen.add_pin('EXTSEL_CLK', 'EXTSEL_CLK', sar_xy + sar_pins['EXTSEL_CLK']['xy'], sar_pins['EXTSEL_CLK']['layer']) #output pins (just duplicate from lower hierarchy cells) for i in range(num_bits): pn = 'ADCOUT' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) laygen.add_pin('CLKO0', 'CLKO', sar_xy + sar_pins['CLKOUT0']['xy'], sar_pins['CLKOUT0']['layer']) laygen.add_pin('CLKO1', 'CLKO', sar_xy + sar_pins['CLKOUT1']['xy'], sar_pins['CLKOUT1']['layer']) #laygen.add_pin('CLKO2', 'CLKO', sar_xy+sar_pins['CLKOUT2']['xy'], sar_pins['CLKOUT2']['layer']) #probe pins laygen.add_pin('CLK0', 'ICLK', sar_xy + sar_pins['CLK0']['xy'], sar_pins['CLK0']['layer']) laygen.add_pin('CLK1', 'ICLK', sar_xy + sar_pins['CLK1']['xy'], sar_pins['CLK1']['layer']) #laygen.add_pin('CLK2', 'ICLK', sar_xy+sar_pins['CLK2']['xy'], sar_pins['CLK2']['layer']) laygen.add_pin('CLKPRB_SAMP', 'CLKPRB_SAMP', samp_xy + samp_pins['ckpg']['xy'], samp_pins['ckpg']['layer']) #laygen.add_pin('CLKPRB_SAR', 'CLKPRB_SAR', sar_xy+sar_pins['CLKPRB']['xy'], sar_pins['CLKPRB']['layer']) laygen.add_pin('SAMPP', 'SAMPP', sar_xy + sar_pins['SAINP']['xy'], sar_pins['SAINP']['layer']) laygen.add_pin('SAMPM', 'SAMPM', sar_xy + sar_pins['SAINM']['xy'], sar_pins['SAINM']['layer']) laygen.add_pin('SAOP', 'SAOP', sar_xy + sar_pins['SAOP']['xy'], sar_pins['SAOP']['layer']) laygen.add_pin('SAOM', 'SAOM', sar_xy + sar_pins['SAOM']['xy'], sar_pins['SAOM']['layer']) laygen.add_pin('SARCLK', 'SARCLK', sar_xy + sar_pins['SARCLK']['xy'], sar_pins['SARCLK']['layer']) laygen.add_pin('SARCLKB', 'SARCLKB', sar_xy + sar_pins['SARCLKB']['xy'], sar_pins['SARCLKB']['layer']) #laygen.add_pin('COMPOUT', 'COMPOUT', sar_xy+sar_pins['COMPOUT']['xy'], sar_pins['COMPOUT']['layer']) laygen.add_pin('DONE', 'DONE', sar_xy + sar_pins['DONE']['xy'], sar_pins['DONE']['layer']) laygen.add_pin('UP', 'UP', sar_xy + sar_pins['UP']['xy'], sar_pins['UP']['layer']) laygen.add_pin('PHI0', 'PHI0', sar_xy + sar_pins['PHI0']['xy'], sar_pins['PHI0']['layer']) for i in range(num_bits): pn = 'ZP' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'ZMID' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'ZM' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'SB' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) for i in range(num_bits - 1): pn = 'VOL' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'VOR' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) #VDD/VSS pin vddcnt = 0 vsscnt = 0 for p in pdict_m5m6[isar.name]: if p.startswith('VDD'): xy0 = pdict_m5m6_thick[isar.name][p] laygen.pin(name='VDDSAR' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDDSAR') vddcnt += 1 if p.startswith('VSS'): xy0 = pdict_m5m6_thick[isar.name][p] laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS:') #laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS') vsscnt += 1 #extract VDD/VSS grid from samp and make power pins rg_m5m6_thick_temp_samp = 'route_M5_M6_thick_temp_samp' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_samp, instname=isamp.name, inst_pin_prefix=['VDD', 'VSS', 'samp_body'], xy_grid_type='ygrid') pdict_m5m6_thick_temp_samp = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_temp_samp) vddcnt = 0 vsscnt = 0 bodycnt = 0 for p in pdict_m5m6_thick_temp_samp[isamp.name]: if p.startswith('VDD'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='VDDSAMP' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VDDSAMP') vddcnt += 1 if p.startswith('VSS'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS:') #laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS') vsscnt += 1 if p.startswith('samp_body'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='samp_body' + str(bodycnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='samp_body') bodycnt += 1 # VBB pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4) rvbb_m3 = [] for p in pdict_m3m4[isar.name]: if p.startswith('VBB'): laygen.pin(name='bottom_body' + str(p), layer=laygen.layers['pin'][3], xy=pdict_m3m4[isar.name][p], gridname=rg_m3m4, netname='bottom_body')
def generate_tisaradc_body_core(laygen, objectname_pfix, ret_libname, sar_libname, ret_name, sar_name, placement_grid, routing_grid_m3m4, routing_grid_m4m5, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, routing_grid_m6m7_thick, num_bits=9, num_slices=8, origin=np.array([0, 0])): """generate sar array """ pg = placement_grid rg_m3m4 = routing_grid_m3m4 rg_m4m5 = routing_grid_m4m5 rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic rg_m6m7_thick = routing_grid_m6m7_thick # placement # ret/sar iret = laygen.place(name="I" + objectname_pfix + 'RET0', templatename=ret_name, gridname=pg, xy=origin, template_libname=ret_libname) sar_xy = origin + (laygen.get_template_size( ret_name, gridname=pg, libname=ret_libname) * np.array([0, 1])) isar = laygen.relplace(name="I" + objectname_pfix + 'SAR0', templatename=sar_name, gridname=pg, refinstname=iret.name, direction='top', template_libname=sar_libname) sar_template = laygen.templates.get_template(sar_name, sar_libname) sar_pins = sar_template.pins sar_xy = isar.xy[0] ret_template = laygen.templates.get_template(ret_name, ret_libname) ret_pins = ret_template.pins ret_xy = iret.xy[0] #prboundary sar_size = laygen.templates.get_template(sar_name, libname=sar_libname).size ret_size = laygen.templates.get_template(ret_name, libname=ret_libname).size laygen.add_rect( None, np.array([ origin, origin + np.array( [max((sar_size[0], ret_size[0])), sar_size[1] + ret_size[1]]) ]), laygen.layers['prbnd']) pdict_m3m4 = laygen.get_inst_pin_coord(None, None, rg_m3m4) pdict_m4m5 = laygen.get_inst_pin_coord(None, None, rg_m4m5) pdict_m5m6 = laygen.get_inst_pin_coord(None, None, rg_m5m6) pdict_m5m6_thick = laygen.get_inst_pin_coord(None, None, rg_m5m6_thick) pdict_m5m6_thick_basic = laygen.get_inst_pin_coord(None, None, rg_m5m6_thick_basic) #VDD/VSS pins (just duplicate from lower hierarchy cells) vddsampcnt = 0 vddsarcnt = 0 vsscnt = 0 for pn, p in sar_pins.items(): if pn.startswith('VDDSAMP'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin('VDDSAMP' + str(vddsampcnt), 'VDDSAMP', pxy, sar_pins[pn]['layer']) vddsampcnt += 1 if pn.startswith('VDDSAR'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin('VDDSAR' + str(vddsarcnt), 'VDDSAR:', pxy, sar_pins[pn]['layer']) vddsarcnt += 1 if pn.startswith('VSS'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin('VSS' + str(vsscnt), 'VSS:', pxy, sar_pins[pn]['layer']) vsscnt += 1 for pn, p in ret_pins.items(): if pn.startswith('VDD'): pxy = ret_xy + ret_pins[pn]['xy'] laygen.add_pin('VDDSAR' + str(vddsarcnt), 'VDDSAR:', pxy, ret_pins[pn]['layer']) vddsarcnt += 1 if pn.startswith('VSS'): pxy = ret_xy + ret_pins[pn]['xy'] laygen.add_pin('VSS' + str(vsscnt), 'VSS:', pxy, ret_pins[pn]['layer']) vsscnt += 1 #input pins #make virtual grids and route on the grids (assuming drc clearance of each block) rg_m5m6_thick_temp_sig = 'route_M5_M6_thick_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_sig, instname=isar.name, template_libname=sar_libname, inst_pin_prefix=['INP', 'INM'], xy_grid_type='xgrid') pdict_m5m6_thick_temp_sig = laygen.get_inst_pin_coord( None, None, rg_m5m6_thick_temp_sig) inp_x_list = [] inm_x_list = [] num_input_track = 4 in_x0 = pdict_m5m6_thick_temp_sig[isar.name]['INP0'][0][0] in_x1 = pdict_m5m6_thick_temp_sig[isar.name]['INM0'][0][0] in_y0 = pdict_m5m6_thick_temp_sig[isar.name]['INP0'][1][1] in_y1 = in_y0 + 4 in_y2 = in_y1 + 2 * num_input_track for i in range(num_slices): in_x0 = min(in_x0, pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0]) in_x1 = max(in_x1, pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0]) laygen.route( None, laygen.layers['metal'][5], xy0=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0], in_y0 ]), xy1=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0], in_y2 ]), gridname0=rg_m5m6_thick_temp_sig) laygen.route( None, laygen.layers['metal'][5], xy0=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0], in_y0 ]), xy1=np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0], in_y2 ]), gridname0=rg_m5m6_thick_temp_sig) for j in range(num_input_track): laygen.via( None, np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INP' + str(i)][0][0], in_y1 + 2 * j ]), rg_m5m6_thick_temp_sig) laygen.via( None, np.array([ pdict_m5m6_thick_temp_sig[isar.name]['INM' + str(i)][0][0], in_y1 + 2 * j + 1 ]), rg_m5m6_thick_temp_sig) #in_x0 -= 2 #in_x1 += 2 rinp = [] rinm = [] for i in range(num_input_track): rinp.append( laygen.route(None, laygen.layers['metal'][6], xy0=np.array([in_x0, in_y1 + 2 * i]), xy1=np.array([in_x1, in_y1 + 2 * i]), gridname0=rg_m5m6_thick_temp_sig)) rinm.append( laygen.route(None, laygen.layers['metal'][6], xy0=np.array([in_x0, in_y1 + 2 * i + 1]), xy1=np.array([in_x1, in_y1 + 2 * i + 1]), gridname0=rg_m5m6_thick_temp_sig)) laygen.add_pin('INP' + str(i), 'INP', rinp[-1].xy, laygen.layers['pin'][6]) laygen.add_pin('INM' + str(i), 'INM', rinm[-1].xy, laygen.layers['pin'][6]) #retimer output pins for i in range(num_slices): for j in range(num_bits): pn = 'out_' + str(i) + '<' + str(j) + '>' pn_out = 'ADCOUT' + str(i) + '<' + str(j) + '>' xy = pdict_m3m4[iret.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][3], xy0=xy[0], xy1=xy[1], gridname0=rg_m3m4) laygen.create_boundary_pin_form_rect(r, rg_m3m4, pn_out, laygen.layers['pin'][3], size=4, direction='bottom') #extclk pins for i in range(num_slices): pn = 'EXTCLK' + str(i) pn_out = 'EXTCLK' + str(i) xy = pdict_m5m6[isar.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][5], xy0=xy[0], xy1=xy[1], gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(r, rg_m5m6, pn_out, laygen.layers['pin'][5], size=4, direction='bottom') #extclk_sel pins for i in range(num_slices): pn = 'EXTSEL_CLK' + str(i) pn_out = 'EXTSEL_CLK' + str(i) xy = pdict_m5m6[isar.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][5], xy0=xy[0], xy1=xy[1], gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(r, rg_m5m6, pn_out, laygen.layers['pin'][5], size=4, direction='bottom') #asclkd pins for i in range(num_slices): for j in range(4): pn = 'ASCLKD' + str(i) + '<' + str(j) + '>' pn_out = 'ASCLKD' + str(i) + '<' + str(j) + '>' xy = pdict_m5m6[isar.name][pn] xy[0][1] = 0 r = laygen.route(None, layer=laygen.layers['metal'][5], xy0=xy[0], xy1=xy[1], gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(r, rg_m5m6, pn_out, laygen.layers['pin'][5], size=4, direction='bottom') #osp/osm pins for i in range(num_slices): laygen.pin(name='OSP' + str(i), layer=laygen.layers['pin'][4], xy=pdict_m4m5[isar.name]['OSP' + str(i)], gridname=rg_m4m5) laygen.pin(name='OSM' + str(i), layer=laygen.layers['pin'][4], xy=pdict_m4m5[isar.name]['OSM' + str(i)], gridname=rg_m4m5) #vref pins for i in range(num_slices): laygen.pin(name='VREF' + str(i) + '<0>', layer=laygen.layers['pin'][6], xy=pdict_m5m6_thick[isar.name]['VREF' + str(i) + '<0>'], gridname=rg_m5m6_thick) laygen.pin(name='VREF' + str(i) + '<1>', layer=laygen.layers['pin'][6], xy=pdict_m5m6_thick[isar.name]['VREF' + str(i) + '<1>'], gridname=rg_m5m6_thick) laygen.pin(name='VREF' + str(i) + '<2>', layer=laygen.layers['pin'][6], xy=pdict_m5m6_thick[isar.name]['VREF' + str(i) + '<2>'], gridname=rg_m5m6_thick) #sar-retimer routes (data) for i in range(num_slices): for j in range(num_bits): laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0], xy1=pdict_m3m4[iret.name]['in_' + str(i) + '<' + str(j) + '>'][0], track_y=pdict_m4m5[isar.name]['ADCOUT' + str(i) + '<' + str(j) + '>'][0][1] + j * 2 + 2, gridname=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4, extendl=0, extendr=0) #sar-retimer routes (clock) rg_m3m4_temp_clk = 'route_M3_M4_basic_temp_clk' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m3m4, gridname_output=rg_m3m4_temp_clk, instname=iret.name, template_libname=ret_libname, inst_pin_prefix=[ 'clk' + str(2 * i + 1) for i in range(int(num_slices / 2)) ], xy_grid_type='xgrid') pdict_m3m4_temp_clk = laygen.get_inst_pin_coord(None, None, rg_m3m4_temp_clk) for i in range(int(num_slices / 2)): for j in range(4): laygen.route_vhv( layerv0=laygen.layers['metal'][5], layerh=laygen.layers['metal'][4], xy0=pdict_m4m5[isar.name]['CLKO' + str(2 * i + 1)][0], xy1=pdict_m3m4_temp_clk[iret.name]['clk' + str(2 * i + 1)][0], track_y=pdict_m4m5[isar.name]['CLKO0'][0][1] + num_bits * 2 + 2 + 2 * j, gridname=rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4_temp_clk, extendl=0, extendr=0) r = laygen.route( None, layer=laygen.layers['metal'][3], xy0=pdict_m3m4_temp_clk[iret.name]['clk' + str(2 * i + 1)][0], xy1=np.array([ pdict_m3m4_temp_clk[iret.name]['clk' + str(2 * i + 1)][0][0], pdict_m4m5[isar.name]['CLKO0'][0][1] + num_bits * 2 + 2 + 2 * 4 + 1 ]), gridname0=rg_m3m4_temp_clk)
def generate_sar_wsamp(laygen, objectname_pfix, workinglib, samp_lib, space_1x_lib, sar_name, samp_name, space_1x_name, placement_grid, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, num_bits=9, origin=np.array([0, 0])): """generate sar with sampling frontend """ pg = placement_grid rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic #for clock routing # placement # sar isar=laygen.place(name="I" + objectname_pfix + 'SAR0', templatename=sar_name, gridname=pg, xy=origin, template_libname=workinglib) # samp isamp = laygen.relplace(name="I" + objectname_pfix + 'SAMP0', templatename=samp_name, gridname=pg, refinstname=isar.name, direction='top', template_libname=samp_lib) # manual vref1 #ivref1=laygen.place(name="I" + objectname_pfix + 'VREF1', templatename='sar_wsamp_vref1_manual', # gridname=pg, xy=origin, template_libname=workinglib) ivref1=laygen.add_inst(None, workinglib, 'sar_wsamp_vref1_manual', xy=np.array([0, 0])) #prboundary sar_size = laygen.templates.get_template(sar_name, libname=workinglib).size samp_size = laygen.templates.get_template(samp_name, libname=samp_lib).size space_size = laygen.templates.get_template(space_1x_name, libname=space_1x_lib).size #size_x=sar_size[0] size_x=sar_size[0]+2.4 print(laygen.get_inst(ivref1.name, libname=workinglib).size) size_y=int((sar_size[1]+samp_size[1])/space_size[1]+1)*space_size[1] laygen.add_rect(None, np.array([origin, origin+np.array([size_x, size_y])]), laygen.layers['prbnd']) # template handles sar_template = laygen.templates.get_template(sar_name, workinglib) samp_template = laygen.templates.get_template(samp_name, samp_lib) #reference coordinates pdict_m5m6=laygen.get_inst_pin_xy(None, None, rg_m5m6) pdict_m5m6_thick=laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) pdict_m5m6_thick_basic=laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_basic) sar_pins=sar_template.pins samp_pins=samp_template.pins #sar_xy=isar.xy[0] #samp_xy=isamp.xy[0] sar_xy=isar.xy samp_xy=isamp.xy # export_dict will be written to a yaml file for using with StdCellBase export_dict = {'boundaries': {'lib_name': 'tsmcN16_logic_templates', 'lr_width': 8, 'tb_height': 0.5}, 'cells': {'sar_wsamp': {'cell_name': 'sar_wsamp', 'lib_name': workinglib, 'size': [40, 1]}}, 'spaces': [{'cell_name': 'space_4x', 'lib_name': 'tsmcN16_logic_templates', 'num_col': 4}, {'cell_name': 'space_2x', 'lib_name': 'tsmcN16_logic_templates', 'num_col': 2}], 'tech_params': {'col_pitch': 0.09, 'directions': ['x', 'y', 'x', 'y'], 'height': 0.96, 'layers': [2, 3, 4, 5], 'spaces': [0.064, 0.05, 0.05, 0.05], 'widths': [0.032, 0.04, 0.04, 0.04]}} export_ports = dict() #signa lroute (clk/inp/inm) #make virtual grids and route on the grids (assuming drc clearance of each block) rg_m5m6_thick_basic_temp_sig='route_M5_M6_thick_basic_temp_sig' laygenhelper.generate_grids_from_inst(laygen, gridname_input=rg_m5m6_thick_basic, gridname_output=rg_m5m6_thick_basic_temp_sig, instname=isamp.name, inst_pin_prefix=['ckout', 'outp', 'outn'], xy_grid_type='xgrid') pdict_m5m6_thick_basic_temp_sig = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_basic_temp_sig) #clock rclk0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['ckout'][0], xy1=pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1]-np.array([0,1]), gridname0=rg_m5m6_thick_basic_temp_sig) laygen.via(None,pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1], rg_m5m6_thick_basic_temp_sig) laygen.via(None,pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK1'][1], rg_m5m6_thick_basic_temp_sig) #frontend sig inp_y_list=[] inm_y_list=[] for pn, p in pdict_m5m6_thick_basic_temp_sig[isar.name].items(): if pn.startswith('INP'): inp_y_list.append(p[0][1]) pv=np.array([pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0][0], p[0][1]]) laygen.via(None,pv, rg_m5m6_thick_basic_temp_sig) if pn.startswith('INM'): inm_y_list.append(p[0][1]) pv=np.array([pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0][0], p[0][1]]) laygen.via(None,pv, rg_m5m6_thick_basic_temp_sig) inp_y=min(inp_y_list) inm_y=min(inm_y_list) rinp0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0], xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0][0],inp_y-1]), gridname0=rg_m5m6_thick_basic_temp_sig) rinm0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0], xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0][0],inm_y-1]), gridname0=rg_m5m6_thick_basic_temp_sig) #rinp0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INP0'][0][0],inp_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) #rinm0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INM0'][0][0],inm_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) #input pins (just duplicate from lower hierarchy cells) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isamp.name, 'ckin', rg_m3m4)[1]+np.array([-2,0]), xy1=laygen.get_inst_pin_xy(isamp.name, 'ckin', rg_m3m4)[1]+np.array([-2,6]), via0=[0, 0], gridname0=rg_m3m4) CLK_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CLK', layer=laygen.layers['pin'][3], size=4, direction="top") #CLK_pin=laygen.add_pin('CLK', 'CLK', samp_xy+samp_pins['ckin']['xy'], samp_pins['ckin']['layer']) export_ports = add_to_export_ports(export_ports, CLK_pin) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isamp.name, 'inp', rg_m3m4)[1]+np.array([-1,0]), xy1=laygen.get_inst_pin_xy(isamp.name, 'inp', rg_m3m4)[1]+np.array([-1,18]), via0=[0, 0], gridname0=rg_m3m4) inp_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='INP', layer=laygen.layers['pin'][3], size=4, direction="top") #inp_pin=laygen.add_pin('INP', 'INP', samp_xy+samp_pins['inp']['xy'], samp_pins['ckin']['layer']) export_ports = add_to_export_ports(export_ports, inp_pin) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isamp.name, 'inn', rg_m3m4)[1]+np.array([1,0]), xy1=laygen.get_inst_pin_xy(isamp.name, 'inn', rg_m3m4)[1]+np.array([1,18]), via0=[0, 0], gridname0=rg_m3m4) inn_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='INM', layer=laygen.layers['pin'][3], size=4, direction="top") #inn_pin=laygen.add_pin('INM', 'INM', samp_xy+samp_pins['inn']['xy'], samp_pins['ckin']['layer']) export_ports = add_to_export_ports(export_ports, inn_pin) #laygen.route(None, laygen.layers['metal'][4], # xy0=laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0]+np.array([0,0]), # xy1=laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0]+np.array([-5,0]), # via0=[0, 0], gridname0=rg_m3m4) #laygen.route(None, laygen.layers['metal'][5], # xy0=laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m4m5)[0]+np.array([-5,0]), # xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m4m5)[0][0],0])+np.array([-5,9]), # via0=[0, 0], via1=[0, 0], endstyle1="extend", gridname0=rg_m4m5) #laygen.route(None, laygen.layers['metal'][4], # xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0][0],0])+np.array([-5,9]), # xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0][0],0])+np.array([0,9]), # gridname0=rg_m3m4) #rpin=laygen.route(None, laygen.layers['metal'][3], # xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0][0],0])+np.array([0,9]), # xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0][0],0])+np.array([0,0]), # via0=[0, 0], gridname0=rg_m3m4) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0]+np.array([0,0]), xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'SAOP', rg_m3m4)[0][0],laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m3m4)[0][1]]), via0=[0, 0], gridname0=rg_m3m4) laygen.route(None, laygen.layers['metal'][5], xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'SAOP', rg_m4m5)[0][0],laygen.get_inst_pin_xy(isar.name, 'OSP', rg_m4m5)[0][1]]), xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'SAOP', rg_m4m5)[0][0],laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m4m5)[0][1]]), via0=[0, 0], via1=[0, 0], endstyle1="extend", gridname0=rg_m4m5) laygen.route(None, laygen.layers['metal'][4], xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'SAOP', rg_m3m4)[0][0],laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m3m4)[0][1]]), xy1=np.array([laygen.get_inst_pin_xy(isamp.name, 'inp', rg_m3m4)[0][0]-24,laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m3m4)[0][1]]), gridname0=rg_m3m4) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=np.array([laygen.get_inst_pin_xy(isamp.name, 'inp', rg_m3m4)[0][0]-24,laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m3m4)[0][1]]), xy1=laygen.get_inst_pin_xy(isamp.name, 'inp', rg_m3m4)[1]+np.array([-24,18]), via0=[0, 0], gridname0=rg_m3m4) osp_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='OSP', layer=laygen.layers['pin'][3], size=4, direction="top") #osp_pin=laygen.add_pin('OSP', 'OSP', sar_xy+sar_pins['OSP']['xy'], sar_pins['OSP']['layer']) export_ports = add_to_export_ports(export_ports, osp_pin) #laygen.route(None, laygen.layers['metal'][4], # xy0=laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0]+np.array([0,0]), # xy1=laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0]+np.array([4,0]), # via0=[0, 0], gridname0=rg_m3m4) #laygen.route(None, laygen.layers['metal'][5], # xy0=laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m4m5)[0]+np.array([4,0]), # xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m4m5)[0][0],0])+np.array([4,9]), # via0=[0, 0], via1=[0, 0], endstyle1="extend", gridname0=rg_m4m5) #laygen.route(None, laygen.layers['metal'][4], # xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0][0],0])+np.array([4,9]), # xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0][0],0])+np.array([0,9]), # gridname0=rg_m3m4) #rpin=laygen.route(None, laygen.layers['metal'][3], # xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0][0],0])+np.array([0,9]), # xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0][0],0])+np.array([0,0]), # via0=[0, 0], gridname0=rg_m3m4) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0]+np.array([0,0]), xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m3m4)[0][0]+5,laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m3m4)[0][1]]), via0=[0, 0], gridname0=rg_m3m4) laygen.route(None, laygen.layers['metal'][5], xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m4m5)[0][0]+5,laygen.get_inst_pin_xy(isar.name, 'OSM', rg_m4m5)[0][1]]), xy1=np.array([laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m4m5)[0][0]+5,laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m4m5)[0][1]]), via0=[0, 0], via1=[0, 0], endstyle1="extend", gridname0=rg_m4m5) laygen.route(None, laygen.layers['metal'][4], xy0=np.array([laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m3m4)[0][0]+5,laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m3m4)[0][1]]), xy1=np.array([laygen.get_inst_pin_xy(isamp.name, 'inn', rg_m3m4)[0][0]+24,laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m3m4)[0][1]]), gridname0=rg_m3m4) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=np.array([laygen.get_inst_pin_xy(isamp.name, 'inn', rg_m3m4)[0][0]+24,laygen.get_inst_pin_xy(isamp.name, 'ckout', rg_m3m4)[0][1]]), xy1=laygen.get_inst_pin_xy(isamp.name, 'inn', rg_m3m4)[1]+np.array([24,18]), via0=[0, 0], gridname0=rg_m3m4) osn_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='OSM', layer=laygen.layers['pin'][3], size=4, direction="top") #osn_pin=laygen.add_pin('OSM', 'OSM', sar_xy+sar_pins['OSM']['xy'], sar_pins['OSM']['layer']) export_ports = add_to_export_ports(export_ports, osn_pin) # For fader, VREF2=VDD, VREF0=VSS for pn, p in sar_pins.items(): if pn.startswith('VREF<0>'): pxy=sar_xy+sar_pins[pn]['xy'] #vref0_pin=laygen.add_pin(pn, 'VREF<0>', pxy, sar_pins[pn]['layer']) laygen.via(None, xy=np.array([2, 0]), gridname=rg_m5m6_thick, refinstname=isar.name, refpinname=pn) #export_ports = add_to_export_ports(export_ports, vref0_pin) if pn.startswith('VREF<1>'): pxy=sar_xy+sar_pins[pn]['xy'] #vref1_pin=laygen.add_pin(pn, 'VREF<1>', pxy, sar_pins[pn]['layer']) #export_ports = add_to_export_ports(export_ports, vref1_pin) if pn.startswith('VREF<2>'): pxy=sar_xy+sar_pins[pn]['xy'] #vref2_pin=laygen.add_pin(pn, 'VREF<2>', pxy, sar_pins[pn]['layer']) laygen.via(None, xy=np.array([1, 0]), gridname=rg_m5m6_thick, refinstname=isar.name, refpinname=pn) #export_ports = add_to_export_ports(export_ports, vref2_pin) #laygen.add_pin('VREF_M5R<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5R<2>']['xy'], sar_pins['VREF_M5R<2>']['layer']) #laygen.add_pin('VREF_M5R<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5R<1>']['xy'], sar_pins['VREF_M5R<1>']['layer']) #laygen.add_pin('VREF_M5R<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5R<0>']['xy'], sar_pins['VREF_M5R<0>']['layer']) #laygen.add_pin('VREF_M5L<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5L<2>']['xy'], sar_pins['VREF_M5L<2>']['layer']) #laygen.add_pin('VREF_M5L<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5L<1>']['xy'], sar_pins['VREF_M5L<1>']['layer']) #laygen.add_pin('VREF_M5L<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5L<0>']['xy'], sar_pins['VREF_M5L<0>']['layer']) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<1>', rg_m4m5)[0]+np.array([0,9]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<1>', rg_m4m5)[0]+np.array([4,9]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<1>', rg_m3m4)[0]+np.array([4,9]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<1>', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) ckd01_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CKDSEL0<1>', layer=laygen.layers['pin'][3], size=4, direction="bottom") #ckd01_pin=laygen.add_pin('CKDSEL0<1>', 'CKDSEL0<1>', sar_xy+sar_pins['CKDSEL0<1>']['xy'], sar_pins['CKDSEL0<1>']['layer']) export_ports = add_to_export_ports(export_ports, ckd01_pin) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<0>', rg_m4m5)[0]+np.array([0,8]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<0>', rg_m4m5)[0]+np.array([4,8]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<0>', rg_m3m4)[0]+np.array([4,8]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL0<0>', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) ckd00_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CKDSEL0<0>', layer=laygen.layers['pin'][3], size=4, direction="bottom") #ckd00_pin=laygen.add_pin('CKDSEL0<0>', 'CKDSEL0<0>', sar_xy+sar_pins['CKDSEL0<0>']['xy'], sar_pins['CKDSEL0<0>']['layer']) export_ports = add_to_export_ports(export_ports, ckd00_pin) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m4m5)[0]+np.array([0,5]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m4m5)[0]+np.array([4,5]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m3m4)[0]+np.array([4,5]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<1>', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) ckd11_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CKDSEL1<1>', layer=laygen.layers['pin'][3], size=4, direction="bottom") #ckd11_pin=laygen.add_pin('CKDSEL1<1>', 'CKDSEL1<1>', sar_xy+sar_pins['CKDSEL1<1>']['xy'], sar_pins['CKDSEL1<1>']['layer']) export_ports = add_to_export_ports(export_ports, ckd11_pin) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<0>', rg_m4m5)[0]+np.array([0,6]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<0>', rg_m4m5)[0]+np.array([4,6]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<0>', rg_m3m4)[0]+np.array([4,6]), xy1=laygen.get_inst_pin_xy(isar.name, 'CKDSEL1<0>', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) ckd10_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CKDSEL1<0>', layer=laygen.layers['pin'][3], size=4, direction="bottom") #ckd10_pin=laygen.add_pin('CKDSEL1<0>', 'CKDSEL1<0>', sar_xy+sar_pins['CKDSEL1<0>']['xy'], sar_pins['CKDSEL1<0>']['layer']) export_ports = add_to_export_ports(export_ports, ckd10_pin) #laygen.add_pin('EXTCLK', 'EXTCLK', sar_xy+sar_pins['EXTCLK']['xy'], sar_pins['EXTCLK']['layer']) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'EXTSEL_CLK', rg_m4m5)[0]+np.array([0,6]), xy1=laygen.get_inst_pin_xy(isar.name, 'EXTSEL_CLK', rg_m4m5)[0]+np.array([4,6]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'EXTSEL_CLK', rg_m3m4)[0]+np.array([4,6]), xy1=laygen.get_inst_pin_xy(isar.name, 'EXTSEL_CLK', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) extsel_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='EXTSEL_CLK', layer=laygen.layers['pin'][3], size=4, direction="bottom") #extsel_pin=laygen.add_pin('EXTSEL_CLK', 'EXTSEL_CLK', sar_xy+sar_pins['EXTSEL_CLK']['xy'], sar_pins['EXTSEL_CLK']['layer']) export_ports = add_to_export_ports(export_ports, extsel_pin) #output pins (just duplicate from lower hierarchy cells) for i in range(num_bits): pn='ADCOUT'+'<'+str(i)+'>' laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, pn, rg_m4m5)[0]+np.array([0,5+i]), xy1=laygen.get_inst_pin_xy(isar.name, pn, rg_m4m5)[0]+np.array([4,5+i]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, pn, rg_m3m4)[0]+np.array([4,5+i]), xy1=laygen.get_inst_pin_xy(isar.name, pn, rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) adcout_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name=pn, layer=laygen.layers['pin'][3], size=4, direction="bottom") #laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) export_ports = add_to_export_ports(export_ports, adcout_pin) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'CLKOUT0', rg_m4m5)[0]+np.array([0,6]), xy1=laygen.get_inst_pin_xy(isar.name, 'CLKOUT0', rg_m4m5)[0]+np.array([4,6]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'CLKOUT0', rg_m3m4)[0]+np.array([4,6]), xy1=laygen.get_inst_pin_xy(isar.name, 'CLKOUT0', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) clko0_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CLKO0', netname='CLKO', layer=laygen.layers['pin'][3], size=4, direction="bottom") #clko0_pin=laygen.add_pin('CLKO0', 'CLKO', sar_xy+sar_pins['CLKOUT0']['xy'], sar_pins['CLKOUT0']['layer']) export_ports = add_to_export_ports(export_ports, clko0_pin) laygen.route(None, laygen.layers['metal'][4], xy0=laygen.get_inst_pin_xy(isar.name, 'CLKOUT1', rg_m4m5)[0]+np.array([0,8]), xy1=laygen.get_inst_pin_xy(isar.name, 'CLKOUT1', rg_m4m5)[0]+np.array([4,8]), via0=[0, 0], endstyle1="extend", gridname0=rg_m4m5) rpin=laygen.route(None, laygen.layers['metal'][3], xy0=laygen.get_inst_pin_xy(isar.name, 'CLKOUT1', rg_m3m4)[0]+np.array([4,8]), xy1=laygen.get_inst_pin_xy(isar.name, 'CLKOUT1', rg_m3m4)[0]+np.array([4,0]), via0=[0, 0], gridname0=rg_m3m4) clko1_pin=laygen.boundary_pin_from_rect(rpin, gridname=rg_m3m4, name='CLKO2', netname='CLKO', layer=laygen.layers['pin'][3], size=4, direction="bottom") #clko1_pin=laygen.add_pin('CLKO1', 'CLKO', sar_xy+sar_pins['CLKOUT1']['xy'], sar_pins['CLKOUT1']['layer']) export_ports = add_to_export_ports(export_ports, clko1_pin) #laygen.add_pin('CLKO2', 'CLKO', sar_xy+sar_pins['CLKOUT2']['xy'], sar_pins['CLKOUT2']['layer']) ''' #probe pins laygen.add_pin('CLK0', 'ICLK', sar_xy+sar_pins['CLK0']['xy'], sar_pins['CLK0']['layer']) laygen.add_pin('CLK1', 'ICLK', sar_xy+sar_pins['CLK1']['xy'], sar_pins['CLK1']['layer']) #laygen.add_pin('CLK2', 'ICLK', sar_xy+sar_pins['CLK2']['xy'], sar_pins['CLK2']['layer']) laygen.add_pin('CLKPRB_SAMP', 'CLKPRB_SAMP', samp_xy+samp_pins['ckpg']['xy'], samp_pins['ckpg']['layer']) #laygen.add_pin('CLKPRB_SAR', 'CLKPRB_SAR', sar_xy+sar_pins['CLKPRB']['xy'], sar_pins['CLKPRB']['layer']) laygen.add_pin('SAMPP', 'SAMPP', sar_xy+sar_pins['SAINP']['xy'], sar_pins['SAINP']['layer']) laygen.add_pin('SAMPM', 'SAMPM', sar_xy+sar_pins['SAINM']['xy'], sar_pins['SAINM']['layer']) laygen.add_pin('SAOP', 'SAOP', sar_xy+sar_pins['SAOP']['xy'], sar_pins['SAOP']['layer']) laygen.add_pin('SAOM', 'SAOM', sar_xy+sar_pins['SAOM']['xy'], sar_pins['SAOM']['layer']) laygen.add_pin('SARCLK', 'SARCLK', sar_xy+sar_pins['SARCLK']['xy'], sar_pins['SARCLK']['layer']) laygen.add_pin('SARCLKB', 'SARCLKB', sar_xy+sar_pins['SARCLKB']['xy'], sar_pins['SARCLKB']['layer']) #laygen.add_pin('COMPOUT', 'COMPOUT', sar_xy+sar_pins['COMPOUT']['xy'], sar_pins['COMPOUT']['layer']) laygen.add_pin('DONE', 'DONE', sar_xy+sar_pins['DONE']['xy'], sar_pins['DONE']['layer']) laygen.add_pin('UP', 'UP', sar_xy+sar_pins['UP']['xy'], sar_pins['UP']['layer']) laygen.add_pin('PHI0', 'PHI0', sar_xy+sar_pins['PHI0']['xy'], sar_pins['PHI0']['layer']) for i in range(num_bits): pn='ZP'+'<'+str(i)+'>' laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn='ZMID'+'<'+str(i)+'>' laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn='ZM'+'<'+str(i)+'>' laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn='SB'+'<'+str(i)+'>' laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) for i in range(num_bits-1): pn='VOL'+'<'+str(i)+'>' laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn='VOR'+'<'+str(i)+'>' laygen.add_pin(pn, pn, sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer']) ''' #VDD/VSS pin vddcnt=0 vsscnt=0 for p in pdict_m5m6[isar.name]: if p.startswith('VDD'): xy0=pdict_m5m6_thick[isar.name][p] vdd_pin=laygen.pin(name='VDDSAR' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDDSAR') vddcnt+=1 export_ports = add_to_export_ports(export_ports, vdd_pin) if p.startswith('VSS'): xy0=pdict_m5m6_thick[isar.name][p] vss_pin=laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS:') vsscnt+=1 export_ports = add_to_export_ports(export_ports, vss_pin) #extract VDD/VSS grid from samp and make power pins rg_m5m6_thick_temp_samp='route_M5_M6_thick_temp_samp' laygenhelper.generate_grids_from_inst(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_samp, instname=isamp.name, inst_pin_prefix=['VDD', 'VSS'], xy_grid_type='ygrid') pdict_m5m6_thick_temp_samp = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_temp_samp) vddcnt=0 vsscnt=0 for p in pdict_m5m6_thick_temp_samp[isamp.name]: if p.startswith('VDD'): xy0=pdict_m5m6_thick_temp_samp[isamp.name][p] vddsamp_pin=laygen.pin(name='VDDSAMP' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VDDSAMP') vddcnt+=1 export_ports = add_to_export_ports(export_ports, vddsamp_pin) if p.startswith('VSS'): xy0=pdict_m5m6_thick_temp_samp[isamp.name][p] vsssamp_pin=laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS:') vsscnt+=1 export_ports = add_to_export_ports(export_ports, vsssamp_pin) export_dict['cells']['sar_wsamp']['ports'] = export_ports export_dict['cells']['sar_wsamp']['size_um'] = [float(int(size_x*1e3))/1e3, float(int(size_y*1e3))/1e3] #export_dict['cells']['clk_dis_N_units']['num_ways'] = num_ways # print('export_dict:') # pprint(export_dict) # save_path = path.dirname(path.dirname(path.realpath(__file__))) + '/dsn_scripts/' save_path = workinglib #if path.isdir(save_path) == False: # mkdir(save_path) with open(save_path + '_int.yaml', 'w') as f: yaml.dump(export_dict, f, default_flow_style=False)
def generate_tisaradc_body(laygen, objectname_pfix, libname, tisar_core_name, tisar_space_name, tisar_space2_name, placement_grid, routing_grid_m3m4, routing_grid_m4m5, routing_grid_m4m5_basic_thick, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, routing_grid_m6m7_thick, routing_grid_m7m8_thick, num_bits=9, num_slices=8, origin=np.array([0, 0])): """generate sar array """ pg = placement_grid rg_m3m4 = routing_grid_m3m4 rg_m4m5 = routing_grid_m4m5 rg_m4m5 = routing_grid_m4m5 rg_m4m5_basic_thick = routing_grid_m4m5_basic_thick rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic rg_m6m7_thick = routing_grid_m6m7_thick rg_m7m8_thick = routing_grid_m7m8_thick # placement ispace20 = laygen.place(name="I" + objectname_pfix + 'SP20', templatename=tisar_space2_name, gridname=pg, xy=origin, template_libname=libname) space20_template = laygen.templates.get_template(tisar_space2_name, libname) space20_pins=space20_template.pins space20_xy=ispace20.xy space0_origin = laygen.get_template_size(ispace20.cellname, gridname=pg, libname=workinglib)*np.array([1, 0]) ispace0 = laygen.place(name="I" + objectname_pfix + 'SP0', templatename=tisar_space_name, gridname=pg, xy=space0_origin, template_libname=libname) space_template = laygen.templates.get_template(tisar_space_name, libname) space_pins=space_template.pins space0_xy=ispace0.xy sar_origin = space0_origin + laygen.get_template_size(ispace0.cellname, gridname=pg, libname=workinglib)*np.array([1, 0]) isar = laygen.place(name="I" + objectname_pfix + 'SAR0', templatename=tisar_core_name, gridname=pg, xy=sar_origin, template_libname=libname) sar_template = laygen.templates.get_template(tisar_core_name, libname) sar_pins=sar_template.pins sar_xy=isar.xy space1_origin = sar_origin + laygen.get_template_size(isar.cellname, gridname=pg, libname=workinglib)*np.array([1, 0]) ispace1 = laygen.place(name="I" + objectname_pfix + 'SP1', templatename=tisar_space_name, gridname=pg, xy=space1_origin, template_libname=libname) space1_xy=ispace1.xy space21_origin = space1_origin + laygen.get_template_size(ispace1.cellname, gridname=pg, libname=workinglib)*np.array([1, 0]) ispace21 = laygen.place(name="I" + objectname_pfix + 'SP21', templatename=tisar_space2_name, gridname=pg, xy=space21_origin, template_libname=libname) space21_xy=ispace21.xy #prboundary sar_size = laygen.templates.get_template(tisar_core_name, libname=libname).size space_size = laygen.templates.get_template(tisar_space_name, libname=libname).size space2_size = laygen.templates.get_template(tisar_space2_name, libname=libname).size #VDD/VSS/VREF integration rvddclkd=[] rvddsamp=[] rvddsar=[] rvddsar_upper=[] rvref0=[] rvref1=[] rvref2=[] rvssclkd=[] rvsssamp=[] rvsssar=[] rvsssar_upper=[] vddsampcnt=0 vddsarcnt=0 y_vddsar_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 fiugre out htresholds for pn, p in sar_pins.items(): if pn.startswith('VDDCLKD'): pxy=np.array([[0, space0_xy[1]+sar_pins[pn]['xy'][0][1]], [space_size[0]*4+sar_size[0], space1_xy[1]+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] if pn.startswith('VDDSAMP'): pxy=np.array([[0, space0_xy[1]+sar_pins[pn]['xy'][0][1]], [space_size[0]*4+sar_size[0], space1_xy[1]+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] if pn.startswith('VDDSAR'): pxy=np.array([[0, space0_xy[1]+sar_pins[pn]['xy'][0][1]], [space_size[0]*4+sar_size[0], space1_xy[1]+sar_pins[pn]['xy'][1][1]]]) if pxy[0][1] > y_vref0: rvddsar_upper.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) else: rvddsar.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pxy[1][1]>y_vddsar_max: y_vddsar_max=pxy[1][1] if pn.startswith('VREF'): pxy=np.array([[0, space0_xy[1]+sar_pins[pn]['xy'][0][1]], [space_size[0]*4+sar_size[0], space1_xy[1]+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 y_vss_th2=0.5*(y_vddsamp_max+y_vddclkd_min) #find out threshold for pn, p in sar_pins.items(): if pn.startswith('VSS'): pxy=np.array([[0, space0_xy[1]+sar_pins[pn]['xy'][0][1]], [space_size[0]*4+sar_size[0], space1_xy[1]+sar_pins[pn]['xy'][1][1]]]) if pxy[0][1] > y_vss_th2: rvssclkd.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) elif pxy[0][1] > y_vss_th: rvsssamp.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) elif pxy[0][1] > y_vref0: rvsssar_upper.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) else: rvsssar.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) #M7 rails rg_route='route_M6_M7_thick_temp_pwr' laygenhelper.generate_grids_from_inst(laygen, gridname_input=rg_m6m7_thick, gridname_output=rg_route, instname=[isar.name], inst_pin_prefix=['VDD', 'VSS', 'VREF'], xy_grid_type='ygrid') ''' #M7 rails-clkd input_rails_rect = [rvddclkd, rvssclkd] rvddclkd_m7_pre, rvssclkd_m7_pre= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDCLKD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, offset_end_coord=None, offset_start_index=2, offset_end_index=-2) ''' #M7 rails-samp input_rails_rect = [rvddsamp, rvsssamp] rvddsamp_m7_pre, rvsssamp_m7_pre= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAMP_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDSAMP', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, offset_end_coord=None, offset_start_index=2, offset_end_index=-2) #M7 rails-sar_lower input_rails_rect = [rvddsar, rvsssar] rvddsar_m7, rvsssar_m7= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAR_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDSAR', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=2, offset_end_index=-2) #M7 rails-sar_upper(+vref) input_rails_rect = [rvddsar_upper, rvsssar_upper, rvref0, rvsssar_upper, rvref1, rvsssar_upper, rvref2, rvsssar_upper] rvddsar_m7_upper, rvsssar0_m7, rvref0_m7_pre, rvsssar1_m7, rvref1_m7_pre, rvsssar2_m7, rvref2_m7_pre, rvsssar3_m7= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAR_UPPER_M7_', layer=laygen.layers['metal'][7], gridname=rg_route, netnames=['VDDSAR', 'VSS', 'VREF<0>', 'VSS', 'VREF<1>', 'VSS', 'VREF<2>', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=2, offset_end_index=-2) rvsssar_m7_upper_pre=rvsssar0_m7+rvsssar1_m7+rvsssar2_m7+rvsssar3_m7 #extend m7 rails for clkd and samp and vref, rvsssar_m7_upper #rvddclkd_m7=[] #rvssclkd_m7=[] rvddsamp_m7=[] rvsssamp_m7=[] rvref0_m7=[] rvref1_m7=[] rvref2_m7=[] rvsssar_m7_upper=[] ''' for r in rvddclkd_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[1][1]+=12 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvddclkd_m7.append(r2) for r in rvssclkd_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[1][1]+=12 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvssclkd_m7.append(r2) ''' for r in rvddsamp_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) #rxy[0][1]-=1 rxy[1][1]+=24 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvddsamp_m7.append(r2) for r in rvsssamp_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) #rxy[0][1]-=1 rxy[1][1]+=24 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvsssamp_m7.append(r2) #extend upper vss routes in the space area down to zero (for vss short) if r.xy[0][0]<sar_xy[0]: laygen.route(None, laygen.layers['metal'][7], xy0=[rxy[0][0], 0], xy1=rxy[1], gridname0=rg_m6m7_thick) if r.xy[0][0]>sar_xy[0]+sar_template.width: laygen.route(None, laygen.layers['metal'][7], xy0=[rxy[0][0], 0], xy1=rxy[1], gridname0=rg_m6m7_thick) for r in rvref0_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[0][1]-=24 #rxy[1][1]+=24 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvref0_m7.append(r2) for r in rvref1_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[0][1]-=24 #rxy[1][1]+=24 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvref1_m7.append(r2) for r in rvref2_m7_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[0][1]-=24 #rxy[1][1]+=24 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvref2_m7.append(r2) for r in rvsssar_m7_upper_pre: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[0][1]-=24 #rxy[1][1]+=24 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) rvsssar_m7_upper.append(r2) #connect VDDSAR/VSS in sar region for r in rvddsar_m7_upper: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[0][1]=1 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) for r in rvsssar_m7_upper: rxy=laygen.get_rect_xy(r.name, gridname=rg_m6m7_thick, sort=True) rxy[0][1]=1 r2=laygen.route(None, laygen.layers['metal'][7], xy0=rxy[0], xy1=rxy[1], gridname0=rg_m6m7_thick) #connect VSS between sar/samp/clkd in space region ''' for r in rvssclkd_m7: if r.xy[1][0] < sar_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvsssar_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) if r.xy[0][0] > space1_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvsssar_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) ''' #create VSS pins for connection to core for i, r in enumerate(rvsssar_m7): pxy=np.array([[r.xy[0][0],0], r.xy[1]]) laygen.add_rect(None, pxy, laygen.layers['metal'][7]) laygen.add_pin('VSS_SAR_M7_'+str(i), 'VSS', pxy, laygen.layers['pin'][7]) ''' #connect VDDSAMP between samp/clkd in space region for r in rvddclkd_m7: if r.xy[1][0] < sar_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvddsamp_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) if r.xy[0][0] > space1_xy[0]: laygen.add_rect(None, np.array([[r.xy[0][0],rvddsamp_m7[0].xy[0][1]], r.xy[1]]), laygen.layers['metal'][7]) #M8 routes #input_rails_rect = [rvddclkd_m7, rvssclkd_m7] #rvddclkd_m8, rvssclkd_m8= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_M8_', # layer=laygen.layers['pin'][8], gridname=rg_m7m8_thick, 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=1, offset_end_index=0) input_rails_rect = [rvssclkd_m7, rvddclkd_m7] rvssclkd_m8, rvddclkd_m8= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_CLKD_M8_', layer=laygen.layers['pin'][8], gridname=rg_m7m8_thick, netnames=['VSS', 'VDDSAMP'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) ''' #M8 routes input_rails_rect = [rvsssamp_m7, rvddsamp_m7] rvsssamp_m8, rvddsamp_m8= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAMP_M8_', layer=laygen.layers['pin'][8], gridname=rg_m7m8_thick, netnames=['VSS', 'VDDSAMP'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) input_rails_rect = [rvddsar_m7, rvsssar_m7] rvddsar_m8, rvsssar_m8= laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAR_M8_', layer=laygen.layers['pin'][8], gridname=rg_m7m8_thick, netnames=['VDDSAR', '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) input_rails_rect = [rvref0_m7, rvsssar_m7_upper, rvref1_m7, rvsssar_m7_upper, rvref2_m7, rvsssar_m7_upper] laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_VREF_M8_', layer=laygen.layers['metal'][8], gridname=rg_m7m8_thick, netnames=['VREF<0>', 'VSS', 'VREF<1>', 'VSS', 'VREF<2>', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) #osp/osm route pdict_os_m4m5 = laygen.get_inst_pin_coord(None, None, rg_m4m5_basic_thick) rosp_m5=[] rosm_m5=[] for i in range(num_slices): rh0, rv0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_os_m4m5[isar.name]['OSP'+str(i)][0], pdict_os_m4m5[isar.name]['OSP'+str(i)][0]+np.array([-i-2, -10]), gridname=rg_m4m5_basic_thick) rosp_m5.append(rv0) rh0, rv0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_os_m4m5[isar.name]['OSM'+str(i)][0], pdict_os_m4m5[isar.name]['OSM'+str(i)][0]+np.array([-num_slices-i-2, -10]), gridname=rg_m4m5_basic_thick) rosm_m5.append(rv0) pdict_os_m5m6 = laygen.get_inst_pin_coord(None, None, rg_m5m6_thick) x0=pdict_os_m5m6[isar.name]['VREF0<0>'][0][0]-4*num_slices y0=pdict_os_m5m6[isar.name]['VREF0<0>'][0][1]-8 rosp_m6=[] rosm_m6=[] for i in range(num_slices): xy0=laygen.get_rect_xy(rosp_m5[i].name, gridname=rg_m5m6_thick, sort=True)[0] rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0, np.array([x0, y0-2*i]), gridname=rg_m5m6_thick) laygen.create_boundary_pin_form_rect(rh0, rg_m5m6_thick, 'OSP'+str(i), laygen.layers['pin'][6], size=6, direction='left') rosp_m6.append(rh0) xy0=laygen.get_rect_xy(rosm_m5[i].name, gridname=rg_m5m6_thick, sort=True)[0] rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0, np.array([x0, y0-2*i-1]), gridname=rg_m5m6_thick) laygen.create_boundary_pin_form_rect(rh0, rg_m5m6_thick, 'OSM'+str(i), laygen.layers['pin'][6], size=6, direction='left') rosm_m6.append(rh0) #other pins - duplicate pin_prefix_list=['INP', 'INM', 'VREF', 'ASCLKD', 'EXTSEL_CLK', 'ADCOUT', 'CLKOUT_DES', 'CLKBOUT_NC', 'CLKCAL', 'RSTP', 'RSTN', 'CLKIP', 'CLKIN'] for pn, p in sar_pins.items(): for pfix in pin_prefix_list: if pn.startswith(pfix): laygen.add_pin(pn, sar_pins[pn]['netname'], sar_xy+sar_pins[pn]['xy'], sar_pins[pn]['layer'])