def generate_tisaradc_space(laygen, objectname_pfix, tisar_libname, space_libname, tisar_name, space_name, placement_grid, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, origin=np.array([0, 0])): """generate tisar space """ pg = placement_grid ttisar = laygen.templates.get_template(tisar_name, libname=tisar_libname) tspace = laygen.templates.get_template(space_name, libname=space_libname) tbnd_bottom = laygen.templates.get_template('boundary_bottom') tbnd_bleft = laygen.templates.get_template('boundary_bottomleft') space_xy = np.array([tspace.size[0], ttisar.size[1]]) laygen.add_rect( None, np.array([ origin, origin + space_xy + 2 * tbnd_bleft.size[0] * np.array([1, 0]) ]), laygen.layers['prbnd']) num_space = int( (ttisar.size[1] - 2 * tbnd_bottom.size[1]) / tspace.size[1]) #space_xy=np.array([tspace.size[0], 56.88]) #change it after finishing the clock part #num_space=int((56.88-2*tbnd_bottom.size[1])/tspace.size[1]) #should be changed after finishing the clock part space_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) ispace = [ laygen.place(name="I" + objectname_pfix + 'SP0', templatename=space_name, gridname=pg, xy=space_origin, template_libname=space_libname) ] #devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'] #devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'] devname_bnd_left = ['ptap_fast_left', 'ntap_fast_left'] devname_bnd_right = ['ptap_fast_right', 'ntap_fast_right'] transform_bnd_left = ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] for i in range(1, num_space): if i % 2 == 0: ispace.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i), templatename=space_name, gridname=pg, refinstname=ispace[-1].name, direction='top', transform='R0', template_libname=space_libname)) #devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] #devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] devname_bnd_left += ['ptap_fast_left', 'ntap_fast_left'] devname_bnd_right += ['ptap_fast_right', 'ntap_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: ispace.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i), templatename=space_name, gridname=pg, refinstname=ispace[-1].name, direction='top', transform='MX', template_libname=space_libname)) #devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] #devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] devname_bnd_left += ['ntap_fast_left', 'ptap_fast_left'] devname_bnd_right += ['ntap_fast_right', 'ptap_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #transform_bnd_left += ['MX', 'R0'] #transform_bnd_right += ['MX', 'R0'] m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) #vdd/vss #m3 rvdd_xy_m3 = [] rvss_xy_m3 = [] space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins space_origin_phy = laygen.get_inst_bbox_phygrid(ispace[0].name)[0] vddcnt = 0 vsscnt = 0 for pn, p in space_pins.items(): if pn.startswith('VDD'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space])]) laygen.add_rect(None, pxy, p['layer']) rvdd_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vddcnt += 1 if pn.startswith('VSS'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space])]) laygen.add_rect(None, pxy, p['layer']) rvss_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vsscnt += 1 #m4 input_rails_xy = [rvdd_xy_m3, rvss_xy_m3] rvdd_m4, rvss_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, overwrite_num_routes=80, offset_start_index=0, offset_end_index=0) #exclude_phycoord_list=[[23.4,34.7]]) #m5 input_rails_rect = [rvdd_m4, rvss_m4] rvdd_m5, rvss_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m6 (extract VDD/VSS grid from tisar and make power pins) rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VDD' laygenhelper.generate_grids_from_template( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VDD'], xy_grid_type='ygrid') input_rails_rect = [rvdd_m5] rvdd_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VDD'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-1) rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VSS' laygenhelper.generate_grids_from_template( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VSS'], xy_grid_type='ygrid') input_rails_rect = [rvss_m5] rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-2)
def generate_r2r_dac_bcap_array(laygen, objectname_pfix, templib_logic, placement_grid, routing_grid_m4m5, routing_grid_m5m6, rg_m3m4_basic_thick, rg_m5m6_thick, m, num_bits, num_hori, num_vert, origin=np.array([0, 0])): """generate r2rdac """ r2r_name = 'r2r_dac_bcap_vref' sar_name = 'sar_wsamp' ret_name = 'adc_retimer' tgate_name = 'tgate_' + str(m) + 'x' pg = placement_grid rg_m4m5 = routing_grid_m4m5 rg_m5m6 = routing_grid_m5m6 # rg_m4m5 = routing_grid_m4m5 # rg_m4m5_basic_thick = routing_grid_m4m5_basic_thick # rg_m4m5_thick = routing_grid_m4m5_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 # Calculate reference coordinate x1_phy = laygen.get_template_xy( name=r2r_name, gridname=None, libname=workinglib)[0] * num_hori pin_origin_x = laygen.grids.get_absgrid_x(rg_m5m6_thick_basic, x1_phy) y1_phy = origin[1] + laygen.get_template_xy(name=sar_name, gridname=None, libname=workinglib)[1] \ + laygen.get_template_xy(name=ret_name, gridname=None, libname=workinglib)[1] pin_origin_y = laygen.grids.get_absgrid_y(rg_m5m6, y1_phy) pin_origin_y2_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF<2>_M6_0', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] pin_origin_y1_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF<1>_M6_0', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] pin_origin_y0_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF<0>_M6_0', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] # pin_origin_y0_thick = laygen.grids.get_absgrid_y(rg_m5m6_thick, y0_phy) # placement irdac = [] for i in range(num_vert): if i == 0: irdac.append( laygen.relplace(name="I" + objectname_pfix + 'IBCAP' + str(i), templatename=r2r_name, gridname=pg, refinstname=None, xy=origin, shape=[num_hori, 1], template_libname=workinglib)) else: irdac.append( laygen.relplace(name="I" + objectname_pfix + 'IBCAP' + str(i), templatename=r2r_name, gridname=pg, refinstname=irdac[-1].name, shape=[num_hori, 1], template_libname=workinglib, direction='top')) # output routing for k in range(4): rv2, rh2 = laygen.route_vh( laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy( irdac[2].name, 'I', rg_m5m6_thick, index=np.array([0, 0]))[0] + np.array([2, 0]), xy1=np.array([pin_origin_x, pin_origin_y2_thick + k]), gridname0=rg_m5m6_thick) rv1, rh1 = laygen.route_vh( laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy( irdac[1].name, 'I', rg_m5m6_thick, index=np.array([0, 0]))[0] + np.array([1, 0]), xy1=np.array([pin_origin_x, pin_origin_y1_thick + k]), gridname0=rg_m5m6_thick) rv0, rh0 = laygen.route_vh( laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy( irdac[0].name, 'I', rg_m5m6_thick, index=np.array([0, 0]))[0] + np.array([0, 0]), xy1=np.array([pin_origin_x, pin_origin_y0_thick + k]), gridname0=rg_m5m6_thick) for j in range(num_vert): laygen.via( None, xy=laygen.get_inst_pin_xy( irdac[j].name, 'I', rg_m4m5, index=np.array([0, 0]))[0] + np.array([j, 0]), gridname=rg_m4m5) laygen.boundary_pin_from_rect(rh2, rg_m5m6_thick, 'VREF' + str(k) + '<' + str(2) + '>', laygen.layers['pin'][6], size=4, direction='right', netname='VREF<' + str(2) + '>') laygen.boundary_pin_from_rect(rh1, rg_m5m6_thick, 'VREF' + str(k) + '<' + str(1) + '>', laygen.layers['pin'][6], size=4, direction='right', netname='VREF<' + str(1) + '>') laygen.boundary_pin_from_rect(rh0, rg_m5m6_thick, 'VREF' + str(k) + '<' + str(0) + '>', laygen.layers['pin'][6], size=4, direction='right', netname='VREF<' + str(0) + '>') pin_origin_y2_thick = laygen.grids.get_absgrid_y( rg_m5m6_thick, laygen.grids.get_phygrid_y(rg_m5m6, pin_origin_y + 4 + num_hori * num_vert)) # m5 supply pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) rvdd_m5 = [] rvss_m5 = [] for i in range(num_hori): for p in pdict_m5m6_thick[irdac[0].name]: if p.startswith('VDD'): r0 = laygen.route( None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[0].name, p, rg_m5m6_thick, index=np.array([i, 0]))[0], xy1=laygen.get_inst_pin_xy(irdac[num_vert - 1].name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvdd_m5.append(r0) for p in pdict_m5m6_thick[irdac[0].name]: if p.startswith('VSS'): r0 = laygen.route( None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[0].name, p, rg_m5m6_thick, index=np.array([i, 0]))[0], xy1=laygen.get_inst_pin_xy(irdac[num_vert - 1].name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvss_m5.append(r0) #m6 (extract VDD/VSS grid from tisar and make power pins) tisar_name = 'tisaradc_body_core' tisar_libname = 'adc_sar_generated' rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VDD' # bnd = laygen.get_template(tisar_name, libname=tisar_libname).xy laygenhelper.generate_grids_from_template( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VDD'], bnd=None, xy_grid_type='ygrid') input_rails_rect = [rvdd_m5] rvdd_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VDD'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VSS' laygenhelper.generate_grids_from_template( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VSS'], xy_grid_type='ygrid') input_rails_rect = [rvss_m5] rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0)
def generate_r2r_dac_bcap_array(laygen, objectname_pfix, templib_logic, placement_grid, routing_grid_m4m5, routing_grid_m5m6, rg_m3m4_basic_thick, rg_m5m6_thick, m, num_bits, num_hori, num_vert, origin=np.array([0, 0])): """generate r2rdac """ r2r_name = 'r2r_dac_bcap' sar_name = 'sar_wsamp' tisar_name='tisaradc_body' ret_name = 'adc_retimer' tgate_name = 'tgate_' + str(m) + 'x' pg = placement_grid rg_m4m5 = routing_grid_m4m5 rg_m5m6 = routing_grid_m5m6 # rg_m4m5 = routing_grid_m4m5 # rg_m4m5_basic_thick = routing_grid_m4m5_basic_thick # rg_m4m5_thick = routing_grid_m4m5_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 # Calculate reference coordinate x1_phy = laygen.get_template_xy(name=r2r_name, gridname=None, libname=workinglib)[0] * num_hori pin_origin_x = laygen.grids.get_absgrid_x(rg_m5m6_thick_basic, x1_phy) if use_sf == True and vref_sf == True: y1_phy = origin[1] + laygen.get_template_xy(name=sar_name, gridname=None, libname=workinglib)[1] \ + laygen.get_template_xy(name=ret_name, gridname=None, libname=workinglib)[1] pin_origin_y = laygen.grids.get_absgrid_y(rg_m5m6, y1_phy) elif use_offset == True: pin_origin_y = origin[1] + laygen.get_template_pin_xy(tisar_name, 'OSM'+str(num_slices-1), gridname=rg_m5m6, libname=workinglib)[0][1] - num_slices*2 - 6 else: y1_phy = origin[1] + laygen.get_template_xy(name=sar_name, gridname=None, libname=workinglib)[1] \ + laygen.get_template_xy(name=ret_name, gridname=None, libname=workinglib)[1] pin_origin_y = laygen.grids.get_absgrid_y(rg_m5m6, y1_phy) if use_sf == True: pin_origin_y1_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'SF_BIAS', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] else: pin_origin_y1_thick = origin[1] + 0 \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] if vref_sf == True: pin_origin_y0_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF_SF_BIAS', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] else: pin_origin_y0_thick = origin[1] + 2 \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] # pin_origin_y0_thick = laygen.grids.get_absgrid_y(rg_m5m6_thick, y0_phy) # placement irdac = [] for i in range(num_vert): if i == 0: irdac.append(laygen.relplace(name="I" + objectname_pfix + 'IBCAP' + str(i), templatename=r2r_name, gridname=pg, refinstname=None, xy=origin, shape=[num_hori, 1], template_libname=workinglib)) else: irdac.append(laygen.relplace(name="I" + objectname_pfix + 'IBCAP' + str(i), templatename=r2r_name, gridname=pg, refinstname=irdac[-1].name, shape=[num_hori, 1], template_libname=workinglib, direction='top')) # output routing for i in range(num_hori): for j in range(num_vert): if i == num_hori - 1 and j == num_vert - 1: # VREF_SF_BIAS routing with thick wire rv1, rh1 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy(irdac[j].name, 'I', rg_m5m6_thick, index=np.array([i, 0]))[0] + np.array([j, 0]), xy1=np.array([pin_origin_x, pin_origin_y0_thick]), gridname0=rg_m5m6_thick) laygen.via(None, xy=laygen.get_inst_pin_xy(irdac[j].name, 'I', rg_m4m5, index=np.array([i, 0]))[ 0] + np.array([j, 0]), gridname=rg_m4m5) laygen.boundary_pin_from_rect(rh1, rg_m5m6_thick, 'out<' + str(num_hori * j + i) + '>', laygen.layers['pin'][6], size=4, direction='right') elif num_hori * j + i == num_slices * 2: # SF_BIAS routing with thick wire rv1, rh1 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy(irdac[j].name, 'I', rg_m5m6_thick, index=np.array([i, 0]))[0] + np.array([j, 0]), xy1=np.array([pin_origin_x, pin_origin_y1_thick]), gridname0=rg_m5m6_thick) laygen.via(None, xy=laygen.get_inst_pin_xy(irdac[j].name, 'I', rg_m4m5, index=np.array([i, 0]))[ 0] + np.array([j, 0]), gridname=rg_m4m5) laygen.boundary_pin_from_rect(rh1, rg_m5m6_thick, 'out<' + str(num_hori * j + i) + '>', laygen.layers['pin'][6], size=4, direction='right') else: rv0, rh0 = laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy(irdac[j].name, 'I', rg_m5m6_thick_basic, index=np.array([i, 0]))[0] + np.array([j, 0]), xy1=np.array([pin_origin_x, pin_origin_y + 4 + num_hori * j + i]), gridname0=rg_m5m6_thick_basic) laygen.via(None, xy=laygen.get_inst_pin_xy(irdac[j].name, 'I', rg_m4m5_thick, index=np.array([i, 0]))[ 0] + np.array([j, 0]), gridname=rg_m4m5_thick) laygen.boundary_pin_from_rect(rh0, rg_m5m6_thick_basic, 'out<' + str(num_hori * j + i) + '>', laygen.layers['pin'][6], size=4, direction='right') pin_origin_y2_thick = laygen.grids.get_absgrid_y(rg_m5m6_thick, laygen.grids.get_phygrid_y(rg_m5m6, pin_origin_y + 4 + num_hori * num_vert)) # m5 supply pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) rvdd_m5 = [] rvss_m5 = [] for i in range(num_hori): for p in pdict_m5m6_thick[irdac[0].name]: if p.startswith('VDD'): r0 = laygen.route(None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[0].name, p, rg_m5m6_thick, index=np.array([i, 0]))[ 0], xy1=laygen.get_inst_pin_xy(irdac[num_vert - 1].name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvdd_m5.append(r0) for p in pdict_m5m6_thick[irdac[0].name]: if p.startswith('VSS'): r0 = laygen.route(None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[0].name, p, rg_m5m6_thick, index=np.array([i, 0]))[ 0], xy1=laygen.get_inst_pin_xy(irdac[num_vert - 1].name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvss_m5.append(r0) # m6 # print(pin_origin_y0_thick, pin_origin_y1_thick, pin_origin_y2_thick) # input_rails_rect = [rvdd_m5, rvss_m5] # rvdd_m6_0, rvss_m6_0 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_0_', # layer=laygen.layers['pin'][6], # gridname=rg_m5m6_thick, # netnames=['VDD', 'VSS'], # direction='x', # input_rails_rect=input_rails_rect, # generate_pin=True, # overwrite_start_coord=None, # overwrite_end_coord=None, # offset_start_index=0, # overwrite_end_index=pin_origin_y0_thick - 2) # rvdd_m6_1, rvss_m6_1 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_1_', # layer=laygen.layers['pin'][6], # gridname=rg_m5m6_thick, # netnames=['VDD', 'VSS'], # direction='x', # input_rails_rect=input_rails_rect, # generate_pin=True, # overwrite_start_coord=None, # overwrite_end_coord=None, # overwrite_start_index=pin_origin_y0_thick + 2, # overwrite_end_index=pin_origin_y1_thick - 2) # rvdd_m6_2, rvss_m6_2 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_2_', # layer=laygen.layers['pin'][6], # gridname=rg_m5m6_thick, # netnames=['VDD', 'VSS'], # direction='x', # input_rails_rect=input_rails_rect, # generate_pin=True, # overwrite_start_coord=None, # overwrite_end_coord=None, # overwrite_start_index=pin_origin_y2_thick + 2, # offset_end_index=0) #m6 (extract VDD/VSS grid from tisar and make power pins) tisar_name = 'tisaradc_body_core' tisar_libname = 'adc_sar_generated' rg_m5m6_thick_temp_tisar='route_M5_M6_thick_temp_tisar_VDD' # bnd = laygen.get_template(tisar_name, libname=tisar_libname).xy laygenhelper.generate_grids_from_template(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VDD'], bnd=None, xy_grid_type='ygrid') input_rails_rect = [rvdd_m5] rvdd_m6 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VDD'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_thick_temp_tisar='route_M5_M6_thick_temp_tisar_VSS' laygenhelper.generate_grids_from_template(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VSS'], xy_grid_type='ygrid') input_rails_rect = [rvss_m5] rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0)
def generate_r2r_dac_array(laygen, objectname_pfix, templib_logic, placement_grid, routing_grid_m4m5, routing_grid_m5m6, rg_m3m4_basic_thick, rg_m5m6_thick, m, num_bits, num_hori, num_vert, origin=np.array([0, 0])): """generate r2rdac """ r2r_name = 'r2r_dac_vref' bcap_name = 'r2r_dac_bcap_array_vref' sar_name = 'sar_wsamp' ret_name = 'adc_retimer' tgate_name = 'tgate_' + str(m) + 'x' pg = placement_grid rg_m4m5 = routing_grid_m4m5 rg_m5m6 = routing_grid_m5m6 # rg_m4m5 = routing_grid_m4m5 # rg_m4m5_basic_thick = routing_grid_m4m5_basic_thick # rg_m4m5_thick = routing_grid_m4m5_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 #boundaries x0=laygen.templates.get_template('capdac', workinglib).xy[1][0] - \ laygen.templates.get_template('boundary_bottomleft').xy[1][0]*2 m_bnd_float = x0 / laygen.templates.get_template( 'boundary_bottom').xy[1][0] m_bnd = int(m_bnd_float) if not m_bnd_float == m_bnd: m_bnd += 1 #Calculate reference coordinate bcap_origin = np.array([ laygen.get_template_xy(name=r2r_name, gridname=pg, libname=workinglib)[0] * num_hori, 0 ]) x1_phy = laygen.get_template_xy(name=r2r_name, gridname=None, libname=workinglib)[0]*num_hori \ + laygen.get_template_xy(name=bcap_name, gridname=None, libname=workinglib)[0] pin_origin_x = laygen.grids.get_absgrid_x(rg_m5m6, x1_phy) pin_origin_x_thick = laygen.grids.get_absgrid_x(rg_m5m6_thick, x1_phy) y1_phy = origin[1] + laygen.get_template_xy(name=sar_name, gridname=None, libname=workinglib)[1] \ + laygen.get_template_xy(name=ret_name, gridname=None, libname=workinglib)[1] pin_origin_y = laygen.grids.get_absgrid_y(rg_m5m6, y1_phy) pin_origin_y2_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF<2>_M6_0', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] pin_origin_y1_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF<1>_M6_0', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] pin_origin_y0_thick = origin[1] + \ laygen.get_template_pin_xy(sar_name, 'VREF<0>_M6_0', rg_m5m6_thick, libname=workinglib)[0][1] \ + laygen.get_template_xy(name=ret_name, gridname=rg_m5m6_thick, libname=workinglib)[1] # pin_origin_y0_thick = laygen.grids.get_absgrid_y(rg_m5m6_thick, y0_phy) # placement irdac = [] for i in range(num_vert): if i == 0: irdac.append( laygen.relplace(name="I" + objectname_pfix + 'IRDAC' + str(i), templatename=r2r_name, gridname=pg, refinstname=None, xy=origin, shape=[num_hori, 1], template_libname=workinglib)) else: irdac.append( laygen.relplace(name="I" + objectname_pfix + 'IRDAC' + str(i), templatename=r2r_name, gridname=pg, refinstname=irdac[-1].name, shape=[num_hori, 1], template_libname=workinglib, direction='top')) ibcap = laygen.relplace(name="I" + objectname_pfix + 'IBCAP', templatename=bcap_name, gridname=pg, refinstname=None, xy=bcap_origin, template_libname=workinglib) # output routing print(pin_origin_x) for k in range(4): rv2, rh2 = laygen.route_vh( laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy(irdac[2].name, 'out', rg_m5m6_basic_thick, index=np.array([0, 0]))[0] - np.array([2, -1]), xy1=np.array([pin_origin_x, pin_origin_y2_thick + k]), gridname0=rg_m5m6_basic_thick) rv1, rh1 = laygen.route_vh( laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy(irdac[1].name, 'out', rg_m5m6_basic_thick, index=np.array([0, 0]))[0] - np.array([1, -1]), xy1=np.array([pin_origin_x, pin_origin_y1_thick + k]), gridname0=rg_m5m6_basic_thick) rv0, rh0 = laygen.route_vh( laygen.layers['metal'][5], laygen.layers['metal'][6], xy0=laygen.get_inst_pin_xy(irdac[0].name, 'out', rg_m5m6_basic_thick, index=np.array([0, 0]))[0] - np.array([0, -1]), xy1=np.array([pin_origin_x, pin_origin_y0_thick + k]), gridname0=rg_m5m6_basic_thick) for j in range(num_vert): laygen.via( None, xy=laygen.get_inst_pin_xy( irdac[j].name, 'out', rg_m4m5, index=np.array([0, 0]))[0] - np.array([j, 0]), gridname=rg_m4m5) laygen.boundary_pin_from_rect(rh2, rg_m5m6_thick, 'VREF' + str(k) + '<' + str(2) + '>', laygen.layers['pin'][6], size=4, direction='right', netname='VREF<' + str(2) + '>') laygen.boundary_pin_from_rect(rh1, rg_m5m6_thick, 'VREF' + str(k) + '<' + str(1) + '>', laygen.layers['pin'][6], size=4, direction='right', netname='VREF<' + str(1) + '>') laygen.boundary_pin_from_rect(rh0, rg_m5m6_thick, 'VREF' + str(k) + '<' + str(0) + '>', laygen.layers['pin'][6], size=4, direction='right', netname='VREF<' + str(0) + '>') # input routing # tgate_x = laygen.get_template_xy(tgate_name, gridname=rg_m4m5, libname=logictemplib)[0] for i in range(num_hori): for j in range(num_vert): x_ref = laygen.get_inst_pin_xy(irdac[j].name, 'SEL<0>', rg_m4m5, index=np.array([i, 0]))[1][0] for k in range(num_bits): rh0, rv0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[j].name, 'SEL<' + str(k) + '>', rg_m4m5, index=np.array([i, 0]))[0], xy1=np.array([x_ref + 12 + num_bits * j + k, 0]), gridname0=rg_m4m5) laygen.boundary_pin_from_rect( rv0, rg_m4m5, 'SEL<' + str((num_hori * j + i) * num_bits + k) + '>', laygen.layers['pin'][5], size=4, direction='bottom') # m5 supply pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) rvdd_m5 = [] rvss_m5 = [] for i in range(num_hori): for p in pdict_m5m6_thick[irdac[0].name]: if p.startswith('VDD'): r0 = laygen.route( None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[0].name, p, rg_m5m6_thick, index=np.array([i, 0]))[0], xy1=laygen.get_inst_pin_xy(irdac[num_vert - 1].name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvdd_m5.append(r0) for p in pdict_m5m6_thick[irdac[0].name]: if p.startswith('VSS'): r0 = laygen.route( None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac[0].name, p, rg_m5m6_thick, index=np.array([i, 0]))[0], xy1=laygen.get_inst_pin_xy(irdac[num_vert - 1].name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvss_m5.append(r0) # m6 (extract VDD/VSS grid from tisar and make power pins) tisar_name = 'tisaradc_body_core' tisar_libname = 'adc_sar_generated' rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VDD' # x_end = laygen.get_template_xy(r2r_name, gridname=rg_m5m6_thick_temp_tisar, libname=workinglib)[0] + \ # laygen.get_template_xy(bcap_name, gridname=rg_m5m6_thick_temp_tisar, libname=workinglib)[0] bnd = laygen.get_template(tisar_name, libname=tisar_libname).xy laygenhelper.generate_grids_from_template( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VDDSAR'], bnd=bnd, xy_grid_type='ygrid') laygen.grids.display(libname=None, gridname=rg_m5m6_thick_temp_tisar) input_rails_rect = [rvdd_m5] rvdd_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VDD'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=pin_origin_x_thick, offset_start_index=0, offset_end_index=0) rg_m5m6_thick_temp_tisar = 'route_M5_M6_thick_temp_tisar_VSS' laygenhelper.generate_grids_from_template( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_tisar, template_name=tisar_name, template_libname=tisar_libname, template_pin_prefix=['VSS'], xy_grid_type='ygrid') laygen.grids.display(libname=None, gridname=rg_m5m6_thick_temp_tisar) input_rails_rect = [rvss_m5] rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick_temp_tisar, netnames=['VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=pin_origin_x_thick, offset_start_index=0, offset_end_index=0)