def generate_clkgcalbuf_wbnd(laygen, objectname_pfix, workinglib, clkgcalbuf_name, placement_grid, origin=np.array([0, 0])): clkgcalbuf_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) iclkgcalbuf=laygen.place(name="I" + objectname_pfix + 'SP0', templatename=clkgcalbuf_name, gridname=pg, xy=clkgcalbuf_origin, template_libname=workinglib) xy0=laygen.get_template_size(name=clkgcalbuf_name, gridname=pg, libname=workinglib) xsp=xy0[0] #ysp=xy0[1] m_bnd = int(xsp / laygen.get_template_size('boundary_bottom', gridname=pg)[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=['nmos4_fast_left', 'pmos4_fast_left'], transform_left=['R0', 'MX'], devname_right=['nmos4_fast_right', 'pmos4_fast_right'], transform_right=['R0', 'MX'], origin=origin) #pins clkgcalbuf_template = laygen.templates.get_template(clkgcalbuf_name, workinglib) clkgcalbuf_pins=clkgcalbuf_template.pins clkgcalbuf_origin_phy = laygen.get_inst_bbox(iclkgcalbuf.name)[0] vddcnt=0 vsscnt=0 for pn, p in clkgcalbuf_pins.items(): if pn.startswith('VDD'): laygen.add_pin('VDD' + str(vddcnt), 'VDD', clkgcalbuf_origin_phy+p['xy'], p['layer']) vddcnt += 1 if pn.startswith('VSS'): laygen.add_pin('VSS' + str(vsscnt), 'VSS', clkgcalbuf_origin_phy+p['xy'], p['layer']) vsscnt += 1 else: laygen.add_pin(pn, p['netname'], clkgcalbuf_origin_phy+p['xy'], p['layer'])
def generate_space_wbnd(laygen, objectname_pfix, workinglib, space_name, placement_grid, origin=np.array([0, 0])): space_origin = origin + laygen.get_xy( obj=laygen.get_template(name='boundary_bottomleft'), gridname=pg) ispace = laygen.place(name="I" + objectname_pfix + 'SP0', templatename=space_name, gridname=pg, xy=space_origin, template_libname=workinglib) xy0 = laygen.get_xy(obj=laygen.get_template(name=space_name, libname=workinglib), gridname=pg) xsp = xy0[0] #ysp=xy0[1] m_bnd = int(xsp / laygen.get_xy( obj=laygen.get_template(name='boundary_bottom'), gridname=pg)[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=['nmos4_fast_left', 'pmos4_fast_left'], transform_left=['R0', 'MX'], devname_right=['nmos4_fast_right', 'pmos4_fast_right'], transform_right=['R0', 'MX'], origin=origin) #pins space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins space_origin_phy = ispace.bbox[0] vddcnt = 0 vsscnt = 0 for pn, p in space_pins.items(): if pn.startswith('VDD'): laygen.add_pin('VDD' + str(vddcnt), 'VDD', space_origin_phy + p['xy'], p['layer']) vddcnt += 1 if pn.startswith('VSS'): laygen.add_pin('VSS' + str(vsscnt), 'VSS', space_origin_phy + p['xy'], p['layer']) vsscnt += 1
def generate_samp(laygen, objectname_pfix, workinglib, placement_grid='placement_basic', routing_grid_m4m5='route_M4_M5_basic_thick', power_grid_m3m4='route_M3_M4_basic_thick', power_grid_m4m5='route_M4_M5_thick', power_grid_m5m6='route_M5_M6_thick', origin=np.array([0, 0])): """generate a sampler with clock buffers. used when AnalogMOS is not available """ #variable/cell namings pg = placement_grid rg45bt = routing_grid_m4m5 pg34bt = power_grid_m3m4 pg45t = power_grid_m4m5 pg56t = power_grid_m5m6 # placement core_origin = origin + laygen.get_xy( obj=laygen.get_template(name='boundary_bottomleft'), gridname=pg) # sampler body isamp = laygen.relplace(name=None, templatename='sarsamp_body', gridname=pg, template_libname=workinglib, transform='R0', xy=core_origin) # clock buffer if tgate == True: ibuf = laygen.relplace(name=None, templatename='sarsamp_buf', gridname=pg, refobj=isamp, direction='top', template_libname=workinglib, transform='MX') else: ibuf = laygen.relplace(name=None, templatename='sarsamp_buf', gridname=pg, refobj=isamp, direction='top', template_libname=workinglib, transform='R0') # boundaries a = laygen.get_xy(obj=laygen.get_template(name='sarsamp_body', libname=workinglib), gridname=pg)[0] b = laygen.get_xy(obj=laygen.get_template(name='boundary_bottom'), gridname=pg)[0] m_bnd = int(a / b) if tgate == True: devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left' ] + ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right' ] + ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] + ['MX', 'R0'] transform_bnd_right = ['R0', 'MX'] + ['MX', 'R0'] else: devname_bnd_left = ['nmos4_fast_left', 'nmos4_fast_left' ] + ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'nmos4_fast_right' ] + ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] + ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] + ['R0', 'MX'] [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) # route x_center=int((laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[1][0] \ -laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[0][0])/2\ +laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[0][0]) y_top = int( laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[1][1]) #in xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='IP', gridname=rg45bt, sort=True)[0] xy1 = [x_center - 3, y_top] rh0, rinp0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='IM', gridname=rg45bt, sort=True)[0] xy1 = [x_center + 3, y_top] rh0, rinn0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) #out xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='OP', gridname=rg45bt, sort=True)[0] xy1 = [x_center - 3, 0] rh0, routp0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='OM', gridname=rg45bt, sort=True)[0] xy1 = [x_center + 3, 0] rh0, routn0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) #en xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='OUT_SW', gridname=rg45bt, sort=True)[0] xy1 = laygen.get_inst_pin_xy(name=isamp.name, pinname='EN', gridname=rg45bt, sort=True)[0] rh0, rckpg0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center - 1, gridname0=rg45bt) rh0, rv0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center + 1, gridname0=rg45bt) #enb if tgate == True: xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='out_int<0>', gridname=rg45bt, sort=True)[0] xy1 = laygen.get_inst_pin_xy(name=isamp.name, pinname='ENB', gridname=rg45bt, sort=True)[0] rh0, rckint0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center - 2, gridname0=rg45bt) rh0, rv0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center + 2, gridname0=rg45bt) #ckin xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='IN', gridname=rg45bt, sort=True)[0] xy1 = [xy0[0], y_top] rh0, rckin0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) #ckout xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='OUT_BUF', gridname=rg45bt, sort=True)[0] xy1 = [x_center, 0] rh0, rckout0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) # signal pins for p, r in zip(['inp', 'inn', 'outp', 'outn', 'ckin', 'ckout', 'ckpg'], [rinp0, rinn0, routp0, routn0, rckin0, rckout0, rckpg0]): laygen.pin(name=p, layer=laygen.layers['pin'][5], refobj=r, gridname=rg45bt) #vdd/vss - route #samp_m3_xy rvss_samp_m3 = [[], []] for pn, p in laygen.get_inst(isamp.name).pins.items(): if pn.startswith('VSSL'): xy = laygen.get_inst_pin_xy(name=isamp.name, pinname=pn, gridname=pg34bt, sort=True) rvss_samp_m3[0].append(xy) if pn.startswith('VSSR'): xy = laygen.get_inst_pin_xy(name=isamp.name, pinname=pn, gridname=pg34bt, sort=True) rvss_samp_m3[1].append(xy) #samp_m4 rvss_samp_m4 = [None, None] input_rails_xy = [rvss_samp_m3[0]] rvss_samp_m4[0] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_SAMPL_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-1)[0] input_rails_xy = [rvss_samp_m3[1]] rvss_samp_m4[1] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_SAMPR_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-1)[0] #buf_m3_xy rvdd_buf_m3 = [[], []] rvss_buf_m3 = [[], []] for pn, p in laygen.get_inst(ibuf.name).pins.items(): if pn.startswith('VSSL'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvss_buf_m3[0].append(xy) if pn.startswith('VSSR'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvss_buf_m3[1].append(xy) if pn.startswith('VDDL'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvdd_buf_m3[0].append(xy) if pn.startswith('VDDR'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvdd_buf_m3[1].append(xy) #buf_m4 rvss_buf_m4 = [None, None] rvdd_buf_m4 = [None, None] input_rails_xy = [rvdd_buf_m3[0], rvss_buf_m3[0]] rvdd_buf_m4[0], rvss_buf_m4[ 0] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_BUFL_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VDD', 'VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) input_rails_xy = [rvdd_buf_m3[1], rvss_buf_m3[1]] rvdd_buf_m4[1], rvss_buf_m4[ 1] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_BUFR_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VDD', 'VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) #m4 rvss_m4 = [ rvss_samp_m4[0] + rvss_buf_m4[0], rvss_samp_m4[1] + rvss_buf_m4[1] ] rvdd_m4 = rvdd_buf_m4 #m5 rvss_m5 = [None, None] rvdd_m5 = [None, None] input_rails_rect = [rvdd_m4[0], rvss_m4[0]] rvdd_m5[0], rvss_m5[0] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M5_', layer=laygen.layers['metal'][5], gridname=pg45t, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_rect = [rvdd_m4[1], rvss_m4[1]] rvdd_m5[1], rvss_m5[1] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M5_', layer=laygen.layers['metal'][5], gridname=pg45t, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m6 input_rails_rect = [rvdd_m5[0] + rvdd_m5[1], rvss_m5[0] + rvss_m5[1]] x1 = laygen.get_inst_bbox( name=ibuf.name, gridname=pg56t)[1][0] + laygen.get_xy( obj=laygen.get_template(name='nmos4_fast_left'), gridname=pg56t)[0] rvdd_m6, rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['metal'][6], gridname=pg56t, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=x1, offset_start_index=0, offset_end_index=0) #trimming and pinning x1_phy = laygen.get_inst_bbox(name=ibuf.name)[1][0] + laygen.get_xy( obj=laygen.get_template(name='nmos4_fast_left'))[0] for r in rvdd_m6: r.xy1[0] = x1_phy p = laygen.pin(name='VDD_M6_' + r.name, layer=laygen.layers['pin'][6], refobj=r, gridname=pg56t, netname='VDD') p.xy1[0] = x1_phy for r in rvss_m6: r.xy1[0] = x1_phy p = laygen.pin(name='VSS_M6_' + r.name, layer=laygen.layers['pin'][6], refobj=r, gridname=pg56t, netname='VSS') p.xy1[0] = x1_phy
def generate_serializer(laygen, objectname_pfix, templib_logic, placement_grid, routing_grid_m2m3, routing_grid_m4m5, num_ser=8, num_ser_3rd=4, m_ser=1, origin=np.array([0, 0])): export_dict = {'boundaries': {'lib_name': 'ge_tech_logic_templates', 'lr_width': 8, 'tb_height': 0.5}, 'cells': {cell_name: {'cell_name': cell_name, 'lib_name': workinglib, 'size': [40, 1]}}, 'spaces': [{'cell_name': 'space_4x', 'lib_name': 'ge_tech_logic_templates', 'num_col': 4}, {'cell_name': 'space_2x', 'lib_name': 'ge_tech_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() pg = placement_grid rg_m2m3 = routing_grid_m2m3 rg_m4m5 = routing_grid_m4m5 sub_ser = int(num_ser/2) ser_name = 'ser_2Nto1_'+str(num_ser)+'to1' ser_3rd_name = 'ser_'+str(num_ser_3rd)+'to1' ser_overall = int(num_ser * num_ser_3rd) # placement iser_3rd=[] for i in range(num_ser): if i==0: iser_3rd.append(laygen.place(name = "I" + objectname_pfix + 'SER3rd'+str(i), templatename = ser_3rd_name, gridname = pg, xy=origin, transform="R0", shape=np.array([1,1]), template_libname = workinglib)) else: iser_3rd.append(laygen.relplace(name = "I" + objectname_pfix + 'SER3rd'+str(i), templatename = ser_3rd_name, gridname = pg, refinstname = iser_3rd[-1].name, transform="R0", shape=np.array([1,1]), template_libname = workinglib, direction = 'top')) refi=iser_3rd[-1] iser_2stg=laygen.relplace(name = "I" + objectname_pfix + 'SER2stg', templatename = ser_name, gridname = pg, refinstname = refi.name, transform="MY", shape=np.array([1,1]), template_libname = workinglib, direction = 'top') #Internal Pins ser2Nto1_clkb_xy=laygen.get_inst_pin_xy(iser_2stg.name, 'CLKB', rg_m3m4) ser2Nto1_clk_xy=laygen.get_inst_pin_xy(iser_2stg.name, 'CLK', rg_m3m4) ser2Nto1_rst_xy=[] ser2Nto1_rst_xy45=[] for i in range(2): ser2Nto1_rst_xy.append(laygen.get_inst_pin_xy(iser_2stg.name, 'RST' + str(i), rg_m3m4)) ser2Nto1_rst_xy45.append(laygen.get_inst_pin_xy(iser_2stg.name, 'RST' + str(i), rg_m4m5)) ser2Nto1_out_xy=laygen.get_inst_pin_xy(iser_2stg.name, 'out', rg_m3m4) ser2Nto1_div_xy=laygen.get_inst_pin_xy(iser_2stg.name, 'divclk', rg_m3m4) ser2Nto1_in_xy=[] ser3rd_in_xy=[] ser3rd_rst_xy=[] ser3rd_rst_xy45=[] ser3rd_clk_xy=[] ser3rd_out_xy=[] for i in range(num_ser): ser2Nto1_in_xy.append(laygen.get_inst_pin_xy(iser_2stg.name, 'in<' + str(i) + '>', rg_m3m4)) ser3rd_rst_xy.append(laygen.get_inst_pin_xy(iser_3rd[i].name, 'RST', rg_m3m4)) ser3rd_rst_xy45.append(laygen.get_inst_pin_xy(iser_3rd[i].name, 'RST', rg_m4m5)) ser3rd_clk_xy.append(laygen.get_inst_pin_xy(iser_3rd[i].name, 'clk_in', rg_m3m4)) ser3rd_out_xy.append(laygen.get_inst_pin_xy(iser_3rd[i].name, 'out', rg_m3m4)) for j in range(num_ser_3rd): ser3rd_in_xy.append(laygen.get_inst_pin_xy(iser_3rd[i].name, 'in<' + str(j) + '>', rg_m3m4)) print(ser3rd_in_xy[10]) # Route for i in range(num_ser): [rh0, rv0, rh1] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][3], ser3rd_out_xy[i][0], ser2Nto1_in_xy[i][0], ser3rd_out_xy[i][0][0]+16+i, rg_m3m4) via_out = laygen.via(None, ser3rd_out_xy[i][0], gridname=rg_m3m4) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], ser2Nto1_div_xy[0], ser3rd_clk_xy[i][1], ser2Nto1_div_xy[0][1]-10, rg_m3m4) via_div = laygen.via(None, ser3rd_clk_xy[i][1], gridname=rg_m3m4) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], ser2Nto1_rst_xy[0][0], ser3rd_rst_xy[i][1]-np.array([5,1]), ser2Nto1_rst_xy[0][0][1]-2, rg_m3m4, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], ser3rd_rst_xy[i][0], ser3rd_rst_xy[i][1]-np.array([5,1]), ser3rd_rst_xy[i][1][1], rg_m3m4, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4) #[rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], # ser2Nto1_rst_xy[0][0], ser2Nto1_rst_xy45[0][0]-np.array([4,1]), ser2Nto1_rst_xy[0][1][1], rg_m3m4, # layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], ser2Nto1_rst_xy[1][0], ser2Nto1_rst_xy[1][1]-np.array([3,1]), ser2Nto1_rst_xy[1][1][1], rg_m3m4, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], ser2Nto1_rst_xy[0][0], ser2Nto1_rst_xy[1][1]-np.array([3,1]), ser2Nto1_rst_xy[0][0][1]-2, rg_m3m4, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4) #Pin #CLK_pin=laygen.pin(name='CLK', layer=laygen.layers['pin'][4], xy=ser2Nto1_clk_xy, gridname=rg_m3m4) rCLK=laygen.route(None, laygen.layers['metal'][4], xy0=ser2Nto1_clk_xy[0], xy1=ser2Nto1_clk_xy[1], gridname0=rg_m3m4) CLK_pin=laygen.boundary_pin_from_rect(rCLK, rg_m3m4, 'CLK', laygen.layers['pin'][4], size=0, direction='top', netname='CLK') export_ports = add_to_export_ports(export_ports, CLK_pin) #CLKB_pin=laygen.pin(name='CLKB', layer=laygen.layers['pin'][4], xy=ser2Nto1_clkb_xy, gridname=rg_m3m4) rCLKB=laygen.route(None, laygen.layers['metal'][4], xy0=ser2Nto1_clkb_xy[0], xy1=ser2Nto1_clkb_xy[1], gridname0=rg_m3m4) CLKB_pin=laygen.boundary_pin_from_rect(rCLKB, rg_m3m4, 'CLKB', laygen.layers['pin'][4], size=0, direction='top', netname='CLKB') export_ports = add_to_export_ports(export_ports, CLKB_pin) #out_pin=laygen.pin(name='out', layer=laygen.layers['pin'][4], xy=ser2Nto1_out_xy, gridname=rg_m3m4) rout=laygen.route(None, laygen.layers['metal'][4], xy0=ser2Nto1_out_xy[0]+np.array([-2,0]), xy1=ser2Nto1_out_xy[1]+np.array([-2,0]), gridname0=rg_m3m4) out_pin=laygen.boundary_pin_from_rect(rout, rg_m3m4, 'out', laygen.layers['pin'][4], size=0, direction='top', netname='out') export_ports = add_to_export_ports(export_ports, out_pin) #RST_pin=laygen.pin(name='RST', layer=laygen.layers['pin'][3], xy=ser2Nto1_rst_xy[1], netname='RST', gridname=rg_m3m4) rRST=laygen.route(None, laygen.layers['metal'][3], xy0=ser2Nto1_rst_xy[1][0], xy1=ser2Nto1_rst_xy[1][1], gridname0=rg_m3m4) RST_pin=laygen.boundary_pin_from_rect(rRST, rg_m3m4, 'RST', laygen.layers['pin'][3], size=0, direction='left', netname='RST') export_ports = add_to_export_ports(export_ports, RST_pin) for i in range(num_ser): for j in range(ser_overall): if j%num_ser==i: in_pin=laygen.pin(name='in<'+str(j)+'>', layer=laygen.layers['pin'][4], xy=ser3rd_in_xy[i*num_ser_3rd+int(j/num_ser)], gridname=rg_m3m4) export_ports = add_to_export_ports(export_ports, in_pin) # power pin pwr_dim=laygen.get_xy(obj=laygen.get_template(name='tap', libname=logictemplib), gridname=rg_m2m3) rvdd = [] rvss = [] print(int(pwr_dim[0])) for i in range(-2, int(pwr_dim[0]/2)*2-2): subser0_vdd_xy=laygen.get_inst_pin_xy(iser_3rd[0].name, 'VDD' + str(i), rg_m2m3) subser0_vss_xy=laygen.get_inst_pin_xy(iser_3rd[0].name, 'VSS' + str(i), rg_m2m3) subser1_vdd_xy=laygen.get_inst_pin_xy(iser_2stg.name, 'VDD' + str(i), rg_m2m3) subser1_vss_xy=laygen.get_inst_pin_xy(iser_2stg.name, 'VSS' + str(i), rg_m2m3) rvdd.append(laygen.route(None, laygen.layers['metal'][3], xy0=np.array([subser1_vdd_xy[1][0],0]), xy1=subser1_vdd_xy[1], gridname0=rg_m2m3)) rvss.append(laygen.route(None, laygen.layers['metal'][3], xy0=np.array([subser1_vss_xy[1][0],0]), xy1=subser1_vss_xy[1], gridname0=rg_m2m3)) VDD_pin=laygen.pin(name = 'VDD'+str(i), layer = laygen.layers['pin'][3], refobj = rvdd[-1], gridname=rg_m2m3, netname='VDD') export_ports = add_to_export_ports(export_ports, VDD_pin) VSS_pin=laygen.pin(name = 'VSS'+str(i), layer = laygen.layers['pin'][3], refobj = rvss[-1], gridname=rg_m2m3, netname='VSS') export_ports = add_to_export_ports(export_ports, VSS_pin) x1=laygen.get_template_size(ser_name, rg_m3m4_thick, workinglib)[0] rvss_m4_xy=[] rvdd_m4_xy=[] for i in range(num_ser): ref_xy=laygen.get_inst_xy(iser_3rd[i].name, rg_m3m4_thick) rvss_m4=laygen.route(None, laygen.layers['metal'][4], xy0=ref_xy, xy1=np.array([x1,ref_xy[1]]), gridname0=rg_m3m4_thick) rvdd_m4=laygen.route(None, laygen.layers['metal'][4], xy0=ref_xy-[0,1], xy1=np.array([x1,ref_xy[1]-1]), gridname0=rg_m3m4_thick) rvss_m4_xy.append(laygen.get_rect_xy(name=rvss_m4.name, gridname=rg_m4m5_thick)) rvdd_m4_xy.append(laygen.get_rect_xy(name=rvdd_m4.name, gridname=rg_m4m5_thick)) ser_xy=laygen.get_inst_xy(iser_2stg.name, rg_m3m4_thick) print(ser_xy) y1=laygen.get_template_size(ser_name, rg_m3m4_thick, workinglib)[1] rvss_2stg_m4=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, ser_xy[1]+y1]), xy1=np.array([x1,ser_xy[1]+y1]), gridname0=rg_m3m4_thick) rvdd_2stg_m4=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, ser_xy[1]+y1-1]), xy1=np.array([x1,ser_xy[1]-1+y1]), gridname0=rg_m3m4_thick) rvss_m4_xy.append(laygen.get_rect_xy(name=rvss_2stg_m4.name, gridname=rg_m4m5_thick)) rvdd_m4_xy.append(laygen.get_rect_xy(name=rvdd_2stg_m4.name, gridname=rg_m4m5_thick)) print(rvss_m4_xy) input_rails_xy = [rvss_m4_xy, rvdd_m4_xy] rvss_m5 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_SER_M5_', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VSS', 'VDD'], direction='y', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) ''' input_rails_xy=[] rvssr_m3_xy=[] rvddr_m3_xy=[] rvssl_m3_xy=[] rvddl_m3_xy=[] for i in range(-2, int(pwr_dim[0]/2)*2-2): if i%2==0: rvssr_m3_xy.append(laygen.get_rect_xy(name=rvss[i].name, gridname=rg_m3m4_thick)) rvddr_m3_xy.append(laygen.get_rect_xy(name=rvdd[i].name, gridname=rg_m3m4_thick)) else: rvssl_m3_xy.append(laygen.get_rect_xy(name=rvss[i].name, gridname=rg_m3m4_thick)) rvddl_m3_xy.append(laygen.get_rect_xy(name=rvdd[i].name, gridname=rg_m3m4_thick)) input_rails_xy = [rvssl_m3_xy, rvddl_m3_xy] rvssl_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_CDRVL_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VSS', 'VDD'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_xy = [rvssr_m3_xy, rvddr_m3_xy] rvssr_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_CDRVL_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VSS', 'VDD'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) ''' # export_dict will be written to a yaml file for using with StdCellBase size_x=laygen.templates.get_template(ser_name, workinglib).xy[1][0] size_y=laygen.templates.get_template(ser_name, workinglib).xy[1][1] + num_ser*laygen.templates.get_template(ser_3rd_name, workinglib).xy[1][1] export_dict['cells'][cell_name]['ports'] = export_ports export_dict['cells'][cell_name]['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 = 'ser_generated' #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_sfft_clkdis_viadel(laygen, objectname_pfix, logictemp_lib, working_lib, grid, origin=np.array([0, 0]), way_order=[0, 8, 1, 7, 2, 6, 3, 5, 4], m_clki=2, m_clko=2, num_bits=5, num_vss_h=4, num_vdd_h=4): """generate cap driver """ pg = grid['pg'] rg_m1m2 = grid['rg_m1m2'] rg_m1m2_thick = grid['rg_m1m2_thick'] rg_m2m3 = grid['rg_m2m3'] rg_m2m3_basic = grid['rg_m2m3_basic'] rg_m2m3_thick = grid['rg_m2m3_thick'] rg_m2m3_thick2 = grid['rg_m2m3_thick2'] rg_m3m4 = grid['rg_m3m4'] rg_m3m4_dense = grid['rg_m3m4_dense'] rg_m3m4_thick2 = grid['rg_m3m4_thick2'] rg_m4m5 = grid['rg_m4m5'] rg_m4m5_thick = grid['rg_m4m5_thick'] rg_m5m6 = grid['rg_m5m6'] rg_m5m6_thick = grid['rg_m5m6_thick'] rg_m6m7 = grid['rg_m6m7'] num_ways = len(way_order) ##Get the index for each way way_index = [] for i in range(num_ways): way_index.append(way_order.index(i)) print(way_index) #Get even and odd index #way_index_even = [] #way_index_odd = [] #for i in range(int(num_ways/2)): #way_index_even.append(way_order.index(2*i)) #way_index_odd.append(way_order.index(2*i+1)) x0 = laygen.templates.get_template('clk_dis_viadel_cell', libname=workinglib).xy[1][0] ##Placing delay cells viacell = [] viacell0 = laygen.place(name='I' + objectname_pfix + 'CELL0', templatename='clk_dis_viadel_cell', gridname=pg, xy=origin, template_libname='clk_dis_generated') viacell.append(viacell0) for i in range(num_ways - 1): viacellx = laygen.relplace(name='I' + objectname_pfix + 'CELL' + str(i + 1), templatename='clk_dis_viadel_cell', gridname=pg, refinstname=viacell[-1].name, template_libname='clk_dis_generated') viacell.append(viacellx) ## Route, connection between different DFFs #wire_num = 0 for i in range(num_ways): wire_num = i % 2 #else: #wire_num = 2 #if (i<int(num_ways-1)): #if ((i!=0) and (flag !=np.sign(way_index[i+1]-way_index[i]))): #wire_num = wire_num + 1 #flag = np.sign(way_index[i+1]-way_index[i]) #print(flag) #else: #wire_num = wire_num + 1 #print(wire_num) #print(wire_num_odd) if (i < int(num_ways) - 1): dff_O_xy = laygen.get_inst_pin_xy(viacell[way_index[i]].name, 'DATAO', rg_m3m4) dff_I_xy = laygen.get_inst_pin_xy(viacell[way_index[i + 1]].name, 'DATAI', rg_m3m4) else: dff_O_xy = laygen.get_inst_pin_xy(viacell[way_index[i]].name, 'DATAO', rg_m3m4) dff_I_xy = laygen.get_inst_pin_xy(viacell[way_index[0]].name, 'DATAI', rg_m3m4) y_cood = dff_I_xy[0][1] laygen.pin(name='DATAO<' + str(way_order[way_index[i]]) + '>', layer=laygen.layers['pin'][3], xy=dff_O_xy, gridname=rg_m3m4) if (i < int(num_ways / 2)): laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], dff_O_xy[0], dff_I_xy[0], y_cood - 7 - wire_num, rg_m3m4) else: laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], dff_O_xy[0], dff_I_xy[0], y_cood - 9 - wire_num, rg_m3m4) ''' if (i<int(num_ways/2)-1): dff_O_xy_even = laygen.get_inst_pin_xy(viacell[way_index_even[i]].name, 'DATAO', rg_m3m4) dff_I_xy_even = laygen.get_inst_pin_xy(viacell[way_index_even[i+1]].name, 'DATAI', rg_m3m4) dff_O_xy_odd = laygen.get_inst_pin_xy(viacell[way_index_odd[i]].name, 'DATAO', rg_m3m4) dff_I_xy_odd = laygen.get_inst_pin_xy(viacell[way_index_odd[i+1]].name, 'DATAI', rg_m3m4) else: dff_O_xy_even = laygen.get_inst_pin_xy(viacell[way_index_even[i]].name, 'DATAO', rg_m3m4) dff_I_xy_even = laygen.get_inst_pin_xy(viacell[way_index_even[0]].name, 'DATAI', rg_m3m4) dff_O_xy_odd = laygen.get_inst_pin_xy(viacell[way_index_odd[i]].name, 'DATAO', rg_m3m4) dff_I_xy_odd = laygen.get_inst_pin_xy(viacell[way_index_odd[0]].name, 'DATAI', rg_m3m4) y_cood = dff_I_xy_even[0][1] laygen.pin(name='DATAO<'+str(way_order[way_index_even[i]])+'>', layer=laygen.layers['pin'][3], xy=dff_I_xy_even, gridname=rg_m3m4) laygen.pin(name='DATAO<'+str(way_order[way_index_odd[i]])+'>', layer=laygen.layers['pin'][3], xy=dff_I_xy_odd, gridname=rg_m3m4) laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], dff_O_xy_even[0], dff_I_xy_even[0], y_cood-7-wire_num_even, rg_m3m4) laygen.route_vhv(laygen.layers['metal'][3], laygen.layers['metal'][4], dff_O_xy_odd[0], dff_I_xy_odd[0], y_cood-7-wire_num_odd, rg_m3m4) ''' ##Route, clock connection from TGATE to input for i in range(num_ways): for j in range(m_clki): viadel_I_xy = laygen.get_inst_pin_xy(viacell[i].name, 'CLKI_' + str(j), rg_m5m6) laygen.pin(name='CLKI' + str(way_order[i]) + '_' + str(j), layer=laygen.layers['pin'][5], xy=viadel_I_xy, gridname=rg_m5m6, netname='CLKI<' + str(way_order[i]) + '>') ##Route, clock connection from TGATE to output for i in range(num_ways): for j in range(m_clko): viadel_I_xy = laygen.get_inst_pin_xy(viacell[i].name, 'CLKO_' + str(j), rg_m5m6) laygen.pin(name='CLKO' + str(way_order[i]) + '_' + str(j), layer=laygen.layers['pin'][5], xy=viadel_I_xy, gridname=rg_m5m6, netname='CLKO<' + str(way_order[i]) + '>') ##Route, for calibration signals #Get the right coodinate on grid m3m4 m2m3_x = laygen.grids.get_absgrid_coord_x(gridname=rg_m2m3_basic, x=x0) m3m4_x = laygen.grids.get_absgrid_coord_x(gridname=rg_m3m4, x=x0) for i in range(num_ways): if i < 0: for j in range(num_bits): viadel_m2m3_xy = laygen.get_inst_pin_xy( viacell[i].name, 'CAL<' + str(j) + '>', rg_m2m3_basic)[1] laygen.route(None, laygen.layers['metal'][3], xy0=viadel_m2m3_xy, xy1=np.array([ viadel_m2m3_xy[0], viadel_m2m3_xy[1] + 5 + j + i * num_bits ]), gridname0=rg_m2m3_basic) laygen.via(None, xy=np.array([ viadel_m2m3_xy[0], viadel_m2m3_xy[1] + 5 + j + i * num_bits ]), gridname=rg_m2m3_basic) calpx = laygen.route( None, laygen.layers['metal'][2], xy0=np.array([0, viadel_m2m3_xy[1] + 5 + j + i * num_bits]), xy1=np.array([ m2m3_x * num_ways, viadel_m2m3_xy[1] + 5 + j + i * num_bits ]), gridname0=rg_m2m3_basic) laygen.boundary_pin_from_rect( calpx, gridname=rg_m2m3_basic, name='CLKCAL' + str(way_order[i]) + '<' + str(j) + '>', layer=laygen.layers['pin'][2], size=2, direction='right') else: for j in range(num_bits): viadel_m2m3_xy = laygen.get_inst_pin_xy( viacell[i].name, 'CAL<' + str(j) + '>', rg_m2m3)[1] laygen.route(None, laygen.layers['metal'][3], xy0=viadel_m2m3_xy, xy1=np.array( [viadel_m2m3_xy[0], viadel_m2m3_xy[1] - 4]), gridname0=rg_m2m3) laygen.via(None, xy=np.array( [viadel_m2m3_xy[0], viadel_m2m3_xy[1] - 4]), gridname=rg_m2m3) ##Route, for set/reset signals #STP and RSTP -- even m2m3_x = laygen.grids.get_absgrid_coord_x(gridname=rg_m2m3_basic, x=x0) viadel_ST_xy = laygen.get_inst_pin_xy(viacell[way_index[0]].name, 'ST', rg_m2m3_basic)[1] laygen.route_vh(laygen.layers['metal'][3], laygen.layers['metal'][2], viadel_ST_xy, np.array([0, viadel_ST_xy[1] + 12]), rg_m2m3_basic) viadel_RST_xy = laygen.get_inst_pin_xy(viacell[way_index[0]].name, 'RST', rg_m2m3)[1] laygen.route(None, laygen.layers['metal'][3], xy0=viadel_RST_xy, xy1=np.array([viadel_RST_xy[0], viadel_RST_xy[1] + 4]), gridname0=rg_m2m3) laygen.via(None, xy=np.array([viadel_RST_xy[0], viadel_RST_xy[1] + 4]), gridname=rg_m2m3) for i in range(int(num_ways) - 1): #way_index viadel_RST_xy = laygen.get_inst_pin_xy(viacell[way_index[i + 1]].name, 'RST', rg_m2m3_basic)[1] laygen.route_vh(laygen.layers['metal'][3], laygen.layers['metal'][2], viadel_RST_xy, np.array([0, viadel_RST_xy[1] + 12]), rg_m2m3_basic) viadel_ST_xy = laygen.get_inst_pin_xy(viacell[way_index[i + 1]].name, 'ST', rg_m2m3)[1] laygen.route(None, laygen.layers['metal'][3], xy0=viadel_ST_xy, xy1=np.array([viadel_ST_xy[0], viadel_ST_xy[1] + 4]), gridname0=rg_m2m3) laygen.via(None, xy=np.array([viadel_ST_xy[0], viadel_ST_xy[1] + 4]), gridname=rg_m2m3) stp = laygen.route(None, laygen.layers['metal'][2], xy0=np.array([0, viadel_RST_xy[1] + 12]), xy1=np.array( [m2m3_x * num_ways - 4, viadel_RST_xy[1] + 12]), gridname0=rg_m2m3_basic) laygen.boundary_pin_from_rect(stp, gridname=rg_m2m3_basic, name='RSTP', layer=laygen.layers['pin'][2], size=2, direction='left') ''' #STN, RSTN -- odd viadel_ST_xy = laygen.get_inst_pin_xy(viacell[way_index_odd[0]].name, 'ST', rg_m2m3_basic)[1] laygen.route_vh(laygen.layers['metal'][3], laygen.layers['metal'][2], viadel_ST_xy, np.array([0,viadel_ST_xy[1]+13]), rg_m2m3_basic) viadel_RST_xy = laygen.get_inst_pin_xy(viacell[way_index_odd[0]].name, 'RST', rg_m2m3)[1] laygen.route(None, laygen.layers['metal'][3], xy0=viadel_RST_xy, xy1=np.array([viadel_RST_xy[0],viadel_RST_xy[1]+4]), gridname0=rg_m2m3) laygen.via(None, xy=np.array([viadel_RST_xy[0],viadel_RST_xy[1]+4]), gridname=rg_m2m3) for i in range(int(num_ways/2)-1):#way_index viadel_RST_xy = laygen.get_inst_pin_xy(viacell[way_index_odd[i+1]].name, 'RST', rg_m2m3_basic)[1] laygen.route_vh(laygen.layers['metal'][3], laygen.layers['metal'][2], viadel_RST_xy, np.array([0,viadel_RST_xy[1]+13]), rg_m2m3_basic) viadel_ST_xy = laygen.get_inst_pin_xy(viacell[way_index_odd[i+1]].name, 'ST', rg_m2m3)[1] laygen.route(None, laygen.layers['metal'][3], xy0=viadel_ST_xy, xy1=np.array([viadel_ST_xy[0],viadel_ST_xy[1]+4]), gridname0=rg_m2m3) laygen.via(None, xy=np.array([viadel_ST_xy[0],viadel_ST_xy[1]+4]), gridname=rg_m2m3) stn=laygen.route(None, laygen.layers['metal'][2], xy0=np.array([0, viadel_RST_xy[1]+13]), xy1=np.array([m2m3_x*num_ways, viadel_RST_xy[1]+13]), gridname0=rg_m2m3_basic) laygen.boundary_pin_from_rect(stn, gridname=rg_m2m3_basic, pinname='RSTN', layer=laygen.layers['pin'][2], size=2, direction='left') ''' ##VDD and VSS pin rvssl_m4 = [] rvssr_m4 = [] rvddl_m4 = [] rvddr_m4 = [] rvdd_m5 = [] rvss_m5 = [] for i in range(num_ways): for j in range(num_vss_h): vssl_xy = laygen.get_inst_pin_xy(viacell[i].name, 'VSS0_' + str(j), rg_m3m4_thick2) rvssl_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vssl_xy[0], xy1=vssl_xy[1], gridname0=rg_m3m4_thick2)) vssr_xy = laygen.get_inst_pin_xy(viacell[i].name, 'VSS1_' + str(j), rg_m3m4_thick2) rvssr_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vssr_xy[0], xy1=vssr_xy[1], gridname0=rg_m3m4_thick2)) # laygen.pin(name='VSS0_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vssl_xy, gridname=rg_m3m4_thick2, netname='VSS') # laygen.pin(name='VSS1_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vssr_xy, gridname=rg_m3m4_thick2, netname='VSS') for j in range(num_vdd_h): vddl_xy = laygen.get_inst_pin_xy(viacell[i].name, 'VDD0_' + str(j), rg_m3m4_thick2) rvddl_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vddl_xy[0], xy1=vddl_xy[1], gridname0=rg_m3m4_thick2)) vddr_xy = laygen.get_inst_pin_xy(viacell[i].name, 'VDD1_' + str(j), rg_m3m4_thick2) rvddr_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vddr_xy[0], xy1=vddr_xy[1], gridname0=rg_m3m4_thick2)) # laygen.pin(name='VDD0_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vddl_xy, gridname=rg_m3m4_thick2, netname='VDD') # laygen.pin(name='VDD1_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vddr_xy, gridname=rg_m3m4_thick2, netname='VDD') rvddl_m5, rvssl_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='M5L', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=[rvddl_m4, rvssl_m4], generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=0, offset_end_index=0) rvddr_m5, rvssr_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='M5L', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=[rvddr_m4, rvssr_m4], generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=0, offset_end_index=-2) rvddl_m4 = [] rvssl_m4 = [] rvddr_m4 = [] rvssr_m4 = [] rvdd_m5 += rvddl_m5 rvdd_m5 += rvddr_m5 rvss_m5 += rvssl_m5 rvss_m5 += rvssr_m5 rvdd_m6, rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='M6', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=[rvdd_m5, rvss_m5], generate_pin=True, overwrite_start_coord=0, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=2, offset_end_index=0)
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_sarafe_nsw(laygen, objectname_pfix, workinglib, placement_grid, routing_grid_m2m3_thick, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, routing_grid_m5m6, routing_grid_m6m7, num_bits=8, num_bits_vertical=6, m_sa=8, origin=np.array([0, 0])): """generate sar analog frontend """ pg = placement_grid rg_m3m4_thick = routing_grid_m3m4_thick rg_m5m6 = routing_grid_m5m6 rg_m6m7 = routing_grid_m6m7 tap_name='tap' cdrv_name='capdrv_nsw_array_'+str(num_bits)+'b' #cdac_name='capdac_'+str(num_bits)+'b' cdac_name='capdac' sa_name='salatch_pmos' # placement xy0 = origin + (laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([1, 0]) ) icdrvl = laygen.place(name="I" + objectname_pfix + 'CDRVL0', templatename=cdrv_name, gridname=pg, xy=xy0, template_libname = workinglib, transform='MY') icdrvr = laygen.place(name="I" + objectname_pfix + 'CDRVR0', templatename=cdrv_name, gridname=pg, xy=xy0, template_libname = workinglib) xy0 = origin + laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([0, 1]) \ + laygen.get_template_size(sa_name, gridname=pg, libname=workinglib) * np.array([0, 1]) isa = laygen.place(name="I" + objectname_pfix + 'SA0', templatename=sa_name, gridname=pg, xy=xy0, template_libname = workinglib, transform='MX') xy0 = origin + laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([0, 1]) \ + laygen.get_template_size(sa_name, gridname=pg, libname=workinglib) * np.array([0, 1]) \ + laygen.get_template_size(cdac_name, gridname=pg, libname=workinglib)*np.array([1, 0]) icdacl = laygen.place(name="I" + objectname_pfix + 'CDACL0', templatename=cdac_name, gridname=pg, xy=xy0, template_libname = workinglib, transform='MY') xy0 = origin + laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([2, 1]) \ + laygen.get_template_size(sa_name, gridname=pg, libname=workinglib) * np.array([0, 1]) \ - laygen.get_template_size(cdac_name, gridname=pg, libname=workinglib)*np.array([1, 0]) icdacr = laygen.place(name="I" + objectname_pfix + 'CDACR0', templatename=cdac_name, gridname=pg, xy=xy0, template_libname = workinglib) # pin informations pdict_m3m4_thick=laygen.get_inst_pin_coord(None, None, rg_m3m4_thick) # internal pins icdrvl_vo_xy = [] icdacl_i_xy = [] icdrvr_vo_xy = [] icdacr_i_xy = [] icdrvl_vo_c0_xy = laygen.get_inst_pin_coord(icdrvl.name, 'VO_C0', rg_m5m6) icdacl_i_c0_xy = laygen.get_inst_pin_coord(icdacl.name, 'I_C0', rg_m5m6) icdrvr_vo_c0_xy = laygen.get_inst_pin_coord(icdrvr.name, 'VO_C0', rg_m5m6) icdacr_i_c0_xy = laygen.get_inst_pin_coord(icdacr.name, 'I_C0', rg_m5m6) for i in range(num_bits): icdrvl_vo_xy.append(laygen.get_inst_pin_coord(icdrvl.name, 'VO<' + str(i) + '>', rg_m5m6)) icdacl_i_xy.append(laygen.get_inst_pin_coord(icdacl.name, 'I<' + str(i) + '>', rg_m5m6)) icdrvr_vo_xy.append(laygen.get_inst_pin_coord(icdrvr.name, 'VO<' + str(i) + '>', rg_m5m6)) icdacr_i_xy.append(laygen.get_inst_pin_coord(icdacr.name, 'I<' + str(i) + '>', rg_m5m6)) #route #capdrv to capdac #y0 = origin[1] + laygen.get_template_size(cdrv_name, gridname=rg_m5m6, libname=workinglib)[1]-2 #refer to capdrv y0 = origin[1] + laygen.get_template_size(cdrv_name, gridname=rg_m5m6, libname=workinglib)[1] \ + laygen.get_template_size(sa_name, gridname=rg_m5m6, libname=workinglib)[1]-4 #refer to sa [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvl_vo_c0_xy[0], icdacl_i_c0_xy[0], y0 + 2, rg_m5m6, layerv1=laygen.layers['metal'][7], gridname1=rg_m6m7) laygen.create_boundary_pin_form_rect(rv0, rg_m5m6, "VOL_C0", laygen.layers['pin'][5], size=4, direction='bottom', netname='VREF<1>') [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvr_vo_c0_xy[0], icdacr_i_c0_xy[0], y0 + 2, rg_m5m6, layerv1=laygen.layers['metal'][7], gridname1=rg_m6m7) laygen.create_boundary_pin_form_rect(rv0, rg_m5m6, "VOR_C0", laygen.layers['pin'][5], size=4, direction='bottom', netname='VREF<1>') for i in range(num_bits): [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvl_vo_xy[i][0], icdacl_i_xy[i][0], y0 - i, rg_m5m6, layerv1=laygen.layers['metal'][7], gridname1=rg_m6m7) laygen.create_boundary_pin_form_rect(rv0, rg_m5m6, "VOL<"+str(i)+">", laygen.layers['pin'][5], size=4, direction='bottom') [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvr_vo_xy[i][0], icdacr_i_xy[i][0], y0 - i, rg_m5m6, layerv1=laygen.layers['metal'][7], gridname1=rg_m6m7) laygen.create_boundary_pin_form_rect(rv0, rg_m5m6, "VOR<"+str(i)+">", laygen.layers['pin'][5], size=4, direction='bottom') #vref rvref0=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='VREF<0>', gridname0=rg_m4m5, refinstname1=icdrvr.name, refpinname1='VREF<0>') rvref1=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='VREF<1>', gridname0=rg_m4m5, refinstname1=icdrvr.name, refpinname1='VREF<1>') rvref2=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='VREF<2>', gridname0=rg_m4m5, refinstname1=icdrvr.name, refpinname1='VREF<2>') #input pins #y0 = laygen.get_inst_pin_coord(icdrvl.name, 'EN0<0>', rg_m4m5, index=np.array([0, 0]), sort=True)[0][1] y0 = 0 rclkb=laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='CLKB', gridname0=rg_m4m5, direction='y') routp=laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='OUTP', gridname0=rg_m4m5, direction='y') routm=laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='OUTM', gridname0=rg_m4m5, direction='y') rosp=laygen.route(None, laygen.layers['metal'][3], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='OSP', gridname0=rg_m2m3, direction='y') rosm=laygen.route(None, laygen.layers['metal'][3], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='OSM', gridname0=rg_m2m3, direction='y') renl0 = [] renl1 = [] renl2 = [] renr0 = [] renr1 = [] renr2 = [] for i in range(num_bits): renl0.append(laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='EN'+str(i)+'<0>', gridname0=rg_m5m6, direction='y')) renl1.append(laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='EN'+str(i)+'<1>', gridname0=rg_m5m6, direction='y')) renl2.append(laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='EN'+str(i)+'<2>', gridname0=rg_m5m6, direction='y')) renr0.append(laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvr.name, refpinname0='EN'+str(i)+'<0>', gridname0=rg_m5m6, direction='y')) renr1.append(laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvr.name, refpinname0='EN'+str(i)+'<1>', gridname0=rg_m5m6, direction='y')) renr2.append(laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvr.name, refpinname0='EN'+str(i)+'<2>', gridname0=rg_m5m6, direction='y')) #inp/inm pdict_m5m6 = laygen.get_inst_pin_coord(None, None, rg_m5m6) outcnt=0 for pn in pdict_m5m6[icdacl.name]: if pn.startswith('O'): #out pin outcnt+=1 x0 = laygen.get_inst_xy(icdacl.name, rg_m5m6)[0] - 8 x1 = laygen.get_inst_xy(icdacr.name, rg_m5m6)[0] + 8 nrin = 16 # number of M6 horizontal route stacks rinp=[] rinm=[] for i in range(nrin): xy0=laygen.get_inst_pin_coord(icdacl.name, "O"+str(outcnt-1-i), rg_m5m6, index=np.array([0, 0]), sort=True)[0] r = laygen.route(None, laygen.layers['metal'][6], xy0=xy0, xy1=np.array([x0, xy0[1]]), gridname0=rg_m5m6) rinp.append(r) xy0=laygen.get_inst_pin_coord(icdacr.name, "O"+str(outcnt-1-i), rg_m5m6, index=np.array([0, 0]), sort=True)[1] r = laygen.route(None, laygen.layers['metal'][6], xy0=xy0, xy1=np.array([x1, xy0[1]]), gridname0=rg_m5m6) rinm.append(r) nrin_sa = 4 # number of M6 horizontal route stacks for cdac to sa for i in range(nrin_sa): xy0=laygen.get_inst_pin_coord(icdacl.name, "O"+str(i), rg_m5m6, index=np.array([0, 0]), sort=True)[0] laygen.route(None, laygen.layers['metal'][6], xy0=xy0, xy1=np.array([x0, xy0[1]]), gridname0=rg_m5m6) for j in range(4): laygen.via(None, [x0-2*j, xy0[1]], rg_m5m6) xy0=laygen.get_inst_pin_coord(icdacr.name, "O"+str(i), rg_m5m6, index=np.array([0, 0]), sort=True)[1] laygen.route(None, laygen.layers['metal'][6], xy0=xy0, xy1=np.array([x1, xy0[1]]), gridname0=rg_m5m6) for j in range(4): laygen.via(None, [x1+2*j, xy0[1]], rg_m5m6) xy0 = laygen.get_inst_pin_coord(isa.name, "INP", rg_m3m4, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_coord(icdacl.name, "O"+str(nrin_sa-1), rg_m5m6, index=np.array([0, 0]), sort=True)[0] for j in range(4): laygen.route(None, laygen.layers['metal'][5], xy0=np.array([x0-2*j, xy0[1]]), xy1=np.array([x0-2*j, xy1[1]]), gridname0=rg_m5m6) xy0 = laygen.get_inst_pin_coord(isa.name, "INM", rg_m4m5, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_coord(icdacr.name, "O"+str(nrin_sa-1), rg_m5m6, index=np.array([0, 0]), sort=True)[0] for j in range(4): laygen.route(None, laygen.layers['metal'][5], xy0=np.array([x1+2*j, xy0[1]]), xy1=np.array([x1+2*j, xy1[1]]), gridname0=rg_m5m6) #inp/inm - sa to capdac xy0 = laygen.get_inst_pin_coord(isa.name, "INP", rg_m4m5, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_coord(isa.name, "INM", rg_m4m5, index=np.array([0, 0]), sort=True)[0] rsainp=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x0-8, xy0[1]]), xy1=xy0, gridname0=rg_m4m5) rsainm=laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x1+8, xy1[1]]), xy1=xy1, gridname0=rg_m4m5) for j in range(4): laygen.via(None, [x0 - 2 * j, xy0[1]], rg_m4m5) laygen.via(None, [x1 + 2 * j, xy1[1]], rg_m4m5) x0 = laygen.get_inst_xy(icdacl.name, rg_m3m4)[0] - 1 x1 = laygen.get_inst_xy(icdacr.name, rg_m3m4)[0] + 1 xy0 = laygen.get_inst_pin_coord(isa.name, "INP", rg_m3m4, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_coord(isa.name, "INM", rg_m3m4, index=np.array([0, 0]), sort=True)[0] laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x0, xy0[1]]), xy1=xy0, gridname0=rg_m3m4, addvia1=True) laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x1, xy1[1]]), xy1=xy1, gridname0=rg_m3m4, addvia1=True) #vdd/vss - route #cdrv_left_m4 rvdd_cdrvl_m3=[] rvss_cdrvl_m3=[] for pn, p in pdict_m3m4_thick[icdrvl.name].items(): if pn.startswith('VDDR'): rvdd_cdrvl_m3.append(p) if pn.startswith('VSSR'): rvss_cdrvl_m3.append(p) input_rails_xy = [rvdd_cdrvl_m3, rvss_cdrvl_m3] rvdd_cdrvl_m4, rvss_cdrvl_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_CDRVL_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=0, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #cdrv_right_m4 x1 = laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=icdrvr.cellname, gridname=rg_m3m4_thick, libname=workinglib)[0] rvdd_cdrvr_m3=[] rvss_cdrvr_m3=[] for pn, p in pdict_m3m4_thick[icdrvr.name].items(): if pn.startswith('VDDR'): rvdd_cdrvr_m3.append(p) if pn.startswith('VSSR'): rvss_cdrvr_m3.append(p) input_rails_xy = [rvdd_cdrvr_m3, rvss_cdrvr_m3] rvdd_cdrvr_m4, rvss_cdrvr_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_CDRVR_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=x1, offset_start_index=0, offset_end_index=0) #sa_left_m4_m5 rvdd_sal_m3=[] rvss_sal_m3=[] for pn, p in pdict_m3m4_thick[isa.name].items(): if pn.startswith('VDDL'): rvdd_sal_m3.append(p) if pn.startswith('VSSL'): rvss_sal_m3.append(p) input_rails_xy = [rvdd_sal_m3, rvss_sal_m3] rvdd_sal_m4, rvss_sal_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_SAL_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=0, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_rect = [rvdd_sal_m4+rvdd_cdrvl_m4, rvss_sal_m4+rvss_cdrvl_m4] rvdd_sal_m5, rvss_sal_m5 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAL_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=0, overwrite_end_coord=None, offset_start_index=1, offset_end_index=-5) #sa_right_m4_m5 x1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=isa.cellname, gridname=rg_m3m4_thick, libname=workinglib)[0] rvdd_sar_m3=[] rvss_sar_m3=[] for pn, p in pdict_m3m4_thick[isa.name].items(): if pn.startswith('VDDR'): rvdd_sar_m3.append(p) if pn.startswith('VSSR'): rvss_sar_m3.append(p) input_rails_xy = [rvdd_sar_m3, rvss_sar_m3] rvdd_sar_m4, rvss_sar_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_SAR_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=x1, offset_start_index=0, offset_end_index=0) input_rails_rect = [rvdd_sar_m4+rvdd_cdrvr_m4, rvss_sar_m4+rvss_cdrvr_m4] rvdd_sar_m5, rvss_sar_m5 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_SAR_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=0, overwrite_end_coord=None, offset_start_index=5, offset_end_index=0) #sa_m6 x1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m5m6_thick)[0]\ +laygen.get_template_size(name=isa.cellname, gridname=rg_m5m6_thick, libname=workinglib)[0] y1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m5m6_thick)[1] input_rails_rect = [rvdd_sal_m5+rvdd_sar_m5, rvss_sal_m5+rvss_sar_m5] rvdd_sa_m6, rvss_sa_m6 = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_', 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=0, overwrite_end_coord=x1, offset_start_index=int(y1/2)+4, offset_end_index=-2+2) #pins laygen.pin(name='VREF<0>', layer=laygen.layers['pin'][4], xy=laygen.get_rect_xy(rvref0.name, rg_m4m5), gridname=rg_m4m5) laygen.pin(name='VREF<1>', layer=laygen.layers['pin'][4], xy=laygen.get_rect_xy(rvref1.name, rg_m4m5), gridname=rg_m4m5) laygen.pin(name='VREF<2>', layer=laygen.layers['pin'][4], xy=laygen.get_rect_xy(rvref2.name, rg_m4m5), gridname=rg_m4m5) t = laygen.templates.get_template(icdrvl.cellname, libname=workinglib) vref0vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_coord(t.name, 'VREF_M5<0>', rg_m4m5, libname=workinglib) vref1vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_coord(t.name, 'VREF_M5<1>', rg_m4m5, libname=workinglib) vref2vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_coord(t.name, 'VREF_M5<2>', rg_m4m5, libname=workinglib) vref0vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_coord(t.name, 'VREF_M5<0>', rg_m4m5, libname=workinglib) vref1vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_coord(t.name, 'VREF_M5<1>', rg_m4m5, libname=workinglib) vref2vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_coord(t.name, 'VREF_M5<2>', rg_m4m5, libname=workinglib) laygen.pin(name='VREF_M5L<0>', layer=laygen.layers['pin'][5], xy=vref0vl_pin_xy, gridname=rg_m4m5, netname='VREF<0>') laygen.pin(name='VREF_M5L<1>', layer=laygen.layers['pin'][5], xy=vref1vl_pin_xy, gridname=rg_m4m5, netname='VREF<1>') laygen.pin(name='VREF_M5L<2>', layer=laygen.layers['pin'][5], xy=vref2vl_pin_xy, gridname=rg_m4m5, netname='VREF<2>') laygen.pin(name='VREF_M5R<0>', layer=laygen.layers['pin'][5], xy=vref0vr_pin_xy, gridname=rg_m4m5, netname='VREF<0>') laygen.pin(name='VREF_M5R<1>', layer=laygen.layers['pin'][5], xy=vref1vr_pin_xy, gridname=rg_m4m5, netname='VREF<1>') laygen.pin(name='VREF_M5R<2>', layer=laygen.layers['pin'][5], xy=vref2vr_pin_xy, gridname=rg_m4m5, netname='VREF<2>') laygen.create_boundary_pin_form_rect(rclkb, rg_m4m5, "CLKB", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(routp, rg_m4m5, "OUTP", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(routm, rg_m4m5, "OUTM", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(rosp, rg_m2m3, "OSP", laygen.layers['pin'][3], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(rosm, rg_m2m3, "OSM", laygen.layers['pin'][3], size=4, direction='bottom') for i in range(num_bits): laygen.create_boundary_pin_form_rect(renl0[i], rg_m5m6, "ENL"+str(i)+"<0>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(renl1[i], rg_m5m6, "ENL"+str(i)+"<1>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(renl2[i], rg_m5m6, "ENL"+str(i)+"<2>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(renr0[i], rg_m5m6, "ENR"+str(i)+"<0>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(renr1[i], rg_m5m6, "ENR"+str(i)+"<1>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.create_boundary_pin_form_rect(renr2[i], rg_m5m6, "ENR"+str(i)+"<2>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.pin_from_rect(name='SAINP', layer=laygen.layers['pin'][4], rect=rsainp, gridname=rg_m4m5, netname='INP') laygen.pin_from_rect(name='SAINM', layer=laygen.layers['pin'][4], rect=rsainm, gridname=rg_m4m5, netname='INM') for i, r in enumerate(rinp): laygen.create_boundary_pin_form_rect(r, rg_m5m6, "INP"+str(i), laygen.layers['pin'][6], size=8, direction='right', netname="INP") for i, r in enumerate(rinm): laygen.create_boundary_pin_form_rect(r, rg_m5m6, "INM"+str(i), laygen.layers['pin'][6], size=8, direction='left', netname="INM")
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_bb_doubleSA' 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_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] 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] # 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 * 3: # 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)
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_clkdis_viadel_htree(laygen, objectname_pfix, logictemp_lib, working_lib, grid, pitch_x, num_ways, trackm, m_clko, num_bits, origin=np.array([0, 0])): """generate htree cell """ pg = grid['pg'] rg_m1m2 = grid['rg_m1m2'] rg_m1m2_thick = grid['rg_m1m2_thick'] rg_m2m3 = grid['rg_m2m3'] rg_m2m3_basic = grid['rg_m2m3_basic'] rg_m2m3_thick = grid['rg_m2m3_thick'] rg_m2m3_thick2 = grid['rg_m2m3_thick2'] rg_m3m4 = grid['rg_m3m4'] rg_m3m4_dense = grid['rg_m3m4_dense'] rg_m3m4_thick2 = grid['rg_m3m4_thick2'] rg_m4m5 = grid['rg_m4m5'] rg_m4m5_thick = grid['rg_m4m5_thick'] rg_m5m6 = grid['rg_m5m6'] rg_m5m6_thick = grid['rg_m5m6_thick'] rg_m6m7 = grid['rg_m6m7'] # trackm = 24 #len_h = laygen.grids.get_absgrid_coord_x(gridname=rg_m4m5, x=20.16) len_h = laygen.grids.get_absgrid_coord_x(gridname=rg_m4m5, x=pitch_x) * num_ways / 16 len_in = laygen.grids.get_absgrid_coord_x(gridname=rg_m4m5, x=2) #num_ways = 8 # num_bits = 5 # m_clko = 2 num_vss_h = 4 num_vdd_h = 4 ##place all viadel and h grids viadel = laygen.place(name='I' + objectname_pfix + 'VIADEL0', templatename='clk_dis_viadel', gridname=pg, xy=origin, template_libname=working_lib) vd_CLKI0_xy = laygen.get_inst_pin_xy(viadel.name, 'CLKI0_' + str(trackm - 1), rg_m4m5)[0] vd_CLKI1_xy = laygen.get_inst_pin_xy(viadel.name, 'CLKI1_' + str(trackm - 1), rg_m4m5)[0] htree0 = laygen.place(name='I' + objectname_pfix + 'HTREE0', templatename='clk_dis_htree', gridname=pg, xy=origin, template_libname=working_lib) ht0_WO_xy = laygen.get_inst_pin_xy(htree0.name, 'WO0_0_0', rg_m4m5)[0] ht0_WI_xy = laygen.get_inst_pin_xy(htree0.name, 'WI_0', rg_m4m5)[0] #move htree0 res_x = laygen.get_grid(gridname=rg_m4m5).width res_y = laygen.get_grid(gridname=rg_m4m5).height htree0.xy = np.array([(vd_CLKI0_xy[0] - ht0_WO_xy[0]) * res_x, (vd_CLKI0_xy[1] - ht0_WO_xy[1]) * res_y]) ht0_WI_xy = np.array([ ht0_WI_xy[0] + (vd_CLKI0_xy[0] - ht0_WO_xy[0]), ht0_WI_xy[1] + (vd_CLKI0_xy[1] - ht0_WO_xy[1]) ]) htree1 = laygen.place(name='I' + objectname_pfix + 'HTREE1', templatename='clk_dis_htree', gridname=pg, xy=origin, template_libname=working_lib) ht1_WO_xy = laygen.get_inst_pin_xy(htree1.name, 'WO0_0_0', rg_m4m5)[0] ht1_WI_xy = laygen.get_inst_pin_xy(htree1.name, 'WI_0', rg_m4m5)[0] #move htree1 #htree1.xy = np.array([(vd_CLKI1_xy[0]-ht1_WO_xy[0])*0.08, (vd_CLKI1_xy[1]-ht1_WO_xy[1])*0.08]) htree1.xy = np.array([(vd_CLKI1_xy[0] - ht1_WO_xy[0]) * res_x, (vd_CLKI1_xy[1] - ht1_WO_xy[1]) * res_y]) ht1_WI_xy = np.array([ ht1_WI_xy[0] + (vd_CLKI1_xy[0] - ht1_WO_xy[0]), ht1_WI_xy[1] + (vd_CLKI1_xy[1] - ht1_WO_xy[1]) ]) #Create input wire #print(ht0_WI_xy) #print(ht1_WI_xy) ##create input vias and metals for i in range(trackm): # for j in range (trackm): # laygen.via(None, xy=np.array([ht0_WI_xy[0]+2*i, ht0_WI_xy[1]+2*j]), gridname=rg_m4m5) # laygen.via(None, xy=np.array([ht1_WI_xy[0]+2*i, ht1_WI_xy[1]+2*j]), gridname=rg_m4m5) vipx = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([ht0_WI_xy[0] + 2 * i, ht0_WI_xy[1]]), xy1=np.array([ ht0_WI_xy[0] + 2 * i, ht0_WI_xy[1] + 2 * (trackm - 1) + trackm ]), gridname0=rg_m4m5) vinx = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([ht1_WI_xy[0] + 2 * i, ht1_WI_xy[1]]), xy1=np.array([ ht1_WI_xy[0] + 2 * i, ht1_WI_xy[1] + 2 * (trackm - 1) + trackm ]), gridname0=rg_m4m5) # laygen.route(None, laygen.layers['metal'][4], xy0=np.array([ht0_WI_xy[0], ht0_WI_xy[1]+2*i]), xy1=np.array([ht0_WI_xy[0]+(len_h*2-2), ht0_WI_xy[1]+2*i]), # gridname0=rg_m4m5) # laygen.route(None, laygen.layers['metal'][4], xy0=np.array([ht1_WI_xy[0]+2*(trackm-1), ht1_WI_xy[1]+2*i]), xy1=np.array([ht1_WI_xy[0]-(len_h*2-2), ht1_WI_xy[1]+2*i]), # gridname0=rg_m4m5) # for j in range (trackm): # laygen.via(None, xy=np.array([ht0_WI_xy[0]+(len_h*2-2)-2*i, ht0_WI_xy[1]+2*j]), gridname=rg_m4m5) # laygen.via(None, xy=np.array([ht1_WI_xy[0]-(len_h*2-2)+2*i, ht1_WI_xy[1]+2*j]), gridname=rg_m4m5) # vipx=laygen.route(None, laygen.layers['metal'][5], xy0=np.array([ht0_WI_xy[0]+(len_h*2-2)-2*i, ht0_WI_xy[1]]), # xy1=np.array([ht0_WI_xy[0]+(len_h*2-2)-2*i, ht0_WI_xy[1]+trackm*2]), # gridname0=rg_m4m5) laygen.boundary_pin_from_rect(vipx, gridname=rg_m4m5, name='CLKIP_' + str(i), layer=laygen.layers['pin'][5], size=2, direction='top', netname='CLKIP') # vinx=laygen.route(None, laygen.layers['metal'][5], xy0=np.array([ht1_WI_xy[0]-(len_h*2-2)+2*i, ht1_WI_xy[1]]), # xy1=np.array([ht1_WI_xy[0]-(len_h*2-2)+2*i, ht1_WI_xy[1]+trackm*2]), # gridname0=rg_m4m5) laygen.boundary_pin_from_rect(vinx, gridname=rg_m4m5, name='CLKIN_' + str(i), layer=laygen.layers['pin'][5], size=2, direction='top', netname='CLKIN') #Create pins #set and rst RST_xy = laygen.get_inst_pin_xy(viadel.name, pinname='RSTP', gridname=rg_m2m3_basic) laygen.pin(name='RSTP', layer=laygen.layers['pin'][2], xy=RST_xy, gridname=rg_m2m3_basic) RST_xy = laygen.get_inst_pin_xy(viadel.name, pinname='RSTN', gridname=rg_m2m3_basic) laygen.pin(name='RSTN', layer=laygen.layers['pin'][2], xy=RST_xy, gridname=rg_m2m3_basic) #CLKCAL for i in range(num_ways): for j in range(num_bits): CAL_xy = laygen.get_inst_pin_xy(viadel.name, pinname='CLKCAL' + str(i) + '<' + str(j) + '>', gridname=rg_m2m3_basic) laygen.pin(name='CLKCAL' + str(i) + '<' + str(j) + '>', layer=laygen.layers['pin'][2], xy=CAL_xy, gridname=rg_m2m3_basic) #CLKO for i in range(num_ways): for j in range(m_clko): CLKO_xy = laygen.get_inst_pin_xy(viadel.name, pinname='CLKO' + str(i) + '_' + str(j), gridname=rg_m5m6) laygen.pin(name='CLKO' + str(i) + '<' + str(j) + '>', layer=laygen.layers['pin'][5], xy=CLKO_xy, gridname=rg_m5m6, netname='CLKO<' + str(i) + '>') #DATAO for i in range(num_ways): DATAO_xy = laygen.get_inst_pin_xy(viadel.name, pinname='DATAO<' + str(i) + '>', gridname=rg_m3m4) laygen.pin(name='DATAO<' + str(i) + '>', layer=laygen.layers['pin'][3], xy=DATAO_xy, gridname=rg_m3m4, netname='DATAO<' + str(i) + '>') ##VDD and VSS pin rvssl_m4 = [] rvssr_m4 = [] rvddl_m4 = [] rvddr_m4 = [] rvdd_m5 = [] rvss_m5 = [] for i in range(num_ways): for j in range(num_vss_h): vssl_xy = laygen.get_inst_pin_xy(viadel.name, 'VSS0_' + str(i) + '_' + str(j), rg_m3m4_thick2) rvssl_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vssl_xy[0], xy1=vssl_xy[1], gridname0=rg_m3m4_thick2)) vssr_xy = laygen.get_inst_pin_xy(viadel.name, 'VSS1_' + str(i) + '_' + str(j), rg_m3m4_thick2) rvssr_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vssr_xy[0], xy1=vssr_xy[1], gridname0=rg_m3m4_thick2)) # laygen.pin(name='VSS0_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vssl_xy, gridname=rg_m3m4_thick2, netname='VSS') # laygen.pin(name='VSS1_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vssr_xy, gridname=rg_m3m4_thick2, netname='VSS') for j in range(num_vdd_h): vddl_xy = laygen.get_inst_pin_xy(viadel.name, 'VDD0_' + str(i) + '_' + str(j), rg_m3m4_thick2) rvddl_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vddl_xy[0], xy1=vddl_xy[1], gridname0=rg_m3m4_thick2)) vddr_xy = laygen.get_inst_pin_xy(viadel.name, 'VDD1_' + str(i) + '_' + str(j), rg_m3m4_thick2) rvddr_m4.append( laygen.route(None, laygen.layers['metal'][4], xy0=vddr_xy[0], xy1=vddr_xy[1], gridname0=rg_m3m4_thick2)) # laygen.pin(name='VDD0_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vddl_xy, gridname=rg_m3m4_thick2, netname='VDD') # laygen.pin(name='VDD1_'+str(i)+'_'+str(j), layer=laygen.layers['pin'][4], xy=vddr_xy, gridname=rg_m3m4_thick2, netname='VDD') rvddl_m5, rvssl_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='M5L', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=[rvddl_m4, rvssl_m4], generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=0, offset_end_index=0) rvddr_m5, rvssr_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='M5L', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=[rvddr_m4, rvssr_m4], generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=0, offset_end_index=-2) rvddl_m4 = [] rvssl_m4 = [] rvddr_m4 = [] rvssr_m4 = [] rvdd_m5 += rvddl_m5 rvdd_m5 += rvddr_m5 rvss_m5 += rvssl_m5 rvss_m5 += rvssr_m5 rvdd_m6, rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='M6', layer=laygen.layers['pin'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=[rvdd_m5, rvss_m5], generate_pin=True, overwrite_start_coord=0, overwrite_end_coord=None, overwrite_num_routes=None, offset_start_index=2, offset_end_index=0) #prboundary size_x = laygen.templates.get_template('clk_dis_viadel', libname='clk_dis_generated').size[0] y_grid = laygen.get_template('tap', libname=logictemplib).size[1] size_y = (int(laygen.get_rect(vinx.name).xy1[1] / y_grid) + 1) * y_grid print('prb:', size_x, size_y) laygen.add_rect(None, np.array([origin, origin + np.array([size_x, size_y])]), laygen.layers['prbnd'])
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' bcap_name='r2r_dac_bcap_array' 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 #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) 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) # 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] # 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] 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 + '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 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, 'out', rg_m5m6_basic_thick, index=np.array([i, 0]))[0] - np.array([j, -1]), xy1=np.array([pin_origin_x, pin_origin_y0_thick]), gridname0=rg_m5m6_basic_thick) laygen.via(None, xy=laygen.get_inst_pin_xy(irdac[j].name, 'out', 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, 'out', rg_m5m6_basic_thick, index=np.array([i, 0]))[0] - np.array([j, -1]), xy1=np.array([pin_origin_x, pin_origin_y1_thick]), gridname0=rg_m5m6_basic_thick) laygen.via(None, xy=laygen.get_inst_pin_xy(irdac[j].name, 'out', 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, 'out', rg_m5m6, 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) laygen.via(None, xy=laygen.get_inst_pin_xy(irdac[j].name, 'out', rg_m4m5, index=np.array([i,0]))[0]-np.array([j,0]), gridname=rg_m4m5) laygen.boundary_pin_from_rect(rh0, rg_m5m6, '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)) # pin_origin_y2_thick=laygen.get_rect_xy(rh0.name, rg_m5m6_thick)[1][1] # 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 # 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=pin_origin_x_thick-2, # 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=pin_origin_x_thick-2, # 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=pin_origin_x_thick-2, # 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' # 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)
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_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_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'])
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_tisaradc_space2(laygen, objectname_pfix, tisar_libname, space_libname, tisar_name, space_name, placement_grid, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, origin=np.array([0, 0])): """generate tisar space """ pg = placement_grid ttisar = laygen.templates.get_template(tisar_name, libname=tisar_libname) tspace = laygen.templates.get_template(space_name, libname=space_libname) sar_pins = ttisar.pins tbnd_bottom = laygen.templates.get_template('boundary_bottom') tbnd_bleft = laygen.templates.get_template('boundary_bottomleft') space_xy = np.array([tspace.size[0], ttisar.size[1]]) laygen.add_rect( None, np.array([ origin, origin + space_xy + 2 * tbnd_bleft.size[0] * np.array([1, 0]) ]), laygen.layers['prbnd']) num_space_tot = int( (ttisar.size[1] - 2 * tbnd_bottom.size[1]) / tspace.size[1]) tbnd_bleft_size = tbnd_bleft.size #VDD/VSS/VREF integration rvddclkd = [] rvddsamp = [] rvddsar = [] rvddsar_upper = [] rvref0 = [] rvref1 = [] rvref2 = [] rvssclkd = [] rvsssamp = [] rvsssar = [] rvsssar_upper = [] vddclkd_xy = [] vddsamp_xy = [] vddsar_xy = [] vddsar_upper_xy = [] vssclkd_xy = [] vsssamp_xy = [] vsssar_xy = [] vsssar_upper_xy = [] y_vddsar_max = 0 y_vddsar_lower_max = 0 y_vddsamp_min = 500000 y_vddsamp_max = 0 y_vddclkd_min = 500000 y_vref0 = sar_pins['VREF0<0>']['xy'][0][1] #categorize vdd pins and figure out thresholds for pn, p in sar_pins.items(): ''' if pn.startswith('VDDCLKD'): pxy=np.array([[0, sar_pins[pn]['xy'][0][1]], [2*tbnd_bleft_size[0]+space_xy[0], sar_pins[pn]['xy'][1][1]]]) rvddclkd.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pxy[1][1]<y_vddclkd_min: y_vddclkd_min=pxy[1][1] vddclkd_xy.append(pxy) ''' if pn.startswith('VDDSAMP'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) rvddsamp.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pxy[1][1] < y_vddsamp_min: y_vddsamp_min = pxy[1][1] if pxy[1][1] > y_vddsamp_max: y_vddsamp_max = pxy[1][1] vddsamp_xy.append(pxy) if pn.startswith('VDDSAR'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) if pxy[0][1] > y_vref0: rvddsar_upper.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vddsar_upper_xy.append(pxy) else: rvddsar.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vddsar_xy.append(pxy) if pxy[1][1] > y_vddsar_lower_max: y_vddsar_lower_max = pxy[1][1] if pxy[1][1] > y_vddsar_max: y_vddsar_max = pxy[1][1] if pn.startswith('VREF'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) if pn.endswith('<0>'): rvref0.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pn.endswith('<1>'): rvref1.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pn.endswith('<2>'): rvref2.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) y_vss_th = 0.5 * (y_vddsar_max + y_vddsamp_min ) #find out threshold (sar/samp) #y_vss_th2=0.5*(y_vddsamp_max+y_vddclkd_min) #(samp/clkd) y_vss_th2 = 100000 for pn, p in sar_pins.items(): if pn.startswith('VSS'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) if pxy[0][1] > y_vss_th2: rvssclkd.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vssclkd_xy.append(pxy) elif pxy[0][1] > y_vss_th: rvsssamp.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vsssamp_xy.append(pxy) elif pxy[0][1] > y_vref0: rvsssar_upper.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vsssar_upper_xy.append(pxy) else: rvsssar.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vsssar_xy.append(pxy) #vddsar cap num_space_sar = int( (y_vss_th - 2 * tbnd_bottom.size[1]) / tspace.size[1]) + 4 space_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) ispace_sar = [ laygen.place(name="I" + objectname_pfix + 'SPSAR0', templatename=space_name, gridname=pg, xy=space_origin, template_libname=space_libname) ] devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] for i in range(1, num_space_sar): if i % 2 == 0: ispace_sar.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_sar[-1].name, direction='top', transform='R0', template_libname=space_libname)) devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: ispace_sar.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_sar[-1].name, direction='top', transform='MX', template_libname=space_libname)) devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAR0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) #vddsamp cap num_space_samp = num_space_tot - num_space_sar - 1 space_origin = origin + laygen.get_template_size( 'boundary_bottomleft', pg) * np.array([1, (3 + 2 * num_space_sar)]) ispace_samp = [ laygen.place(name="I" + objectname_pfix + 'SPSAMP0', templatename=space_name, gridname=pg, xy=space_origin, template_libname=space_libname) ] devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] for i in range(1, num_space_samp): if i % 2 == 0: ispace_samp.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_samp[-1].name, direction='top', transform='R0', template_libname=space_libname)) devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: ispace_samp.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_samp[-1].name, direction='top', transform='MX', template_libname=space_libname)) devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAMP0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=space_origin-laygen.get_template_size('boundary_bottomleft', pg)) #vdd/vss #m3 rvdd_sar_xy_m3 = [] rvss_sar_xy_m3 = [] space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins space_origin_phy = laygen.get_inst_bbox_phygrid(ispace_sar[0].name)[0] vddcnt = 0 vsscnt = 0 for pn, p in space_pins.items(): if pn.startswith('VDD'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_sar])]) pxy[1][1] = y_vddsar_lower_max laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvdd_sar_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vddcnt += 1 if pn.startswith('VSS'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_sar])]) pxy[1][1] = y_vddsar_lower_max laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvss_sar_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vsscnt += 1 rvdd_samp_xy_m3 = [] rvss_samp_xy_m3 = [] space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins space_origin_phy = laygen.get_inst_bbox_phygrid(ispace_samp[0].name)[0] vddcnt = 0 vsscnt = 0 for pn, p in space_pins.items(): if pn.startswith('VDD'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_samp])]) laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvdd_samp_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vddcnt += 1 if pn.startswith('VSS'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_samp])]) laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvss_samp_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vsscnt += 1 #m4 input_rails_xy = [rvdd_samp_xy_m3, rvss_samp_xy_m3] rvdd_samp_m4, rvss_samp_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_SAMP_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDDSAMP', 'VSSSAMP'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_xy = [rvdd_sar_xy_m3, rvss_sar_xy_m3] rvdd_sar_m4, rvss_sar_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_SAR_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDDSAR', 'VSSSAR'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m5 input_rails_rect = [rvdd_samp_m4, rvss_samp_m4] rvdd_samp_m5, rvss_samp_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_SAMP', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_rect = [rvdd_sar_m4, rvss_sar_m4] rvdd_sar_m5, rvss_sar_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_SAR', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m6 (extract VDD/VSS grid from tisar and make power pins) rg_m5m6_sar_vdd = 'route_M5_M6_thick_temp_tisar_sar_vdd' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_sar_vdd, xy=vddsar_xy, xy_grid_type='ygrid') input_rails_rect = [rvdd_sar_m5] [rvdd_sar_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAR_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_sar_vdd, netnames=['VDDSAR'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_sar_vss = 'route_M5_M6_thick_temp_tisar_sar_vss' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_sar_vss, xy=vsssar_xy, xy_grid_type='ygrid') input_rails_rect = [rvss_sar_m5] [rvss_sar_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAR_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_sar_vss, netnames=['VSS:'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_samp = 'route_M5_M6_thick_temp_tisar_samp_vdd' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_samp, xy=vddsamp_xy, xy_grid_type='ygrid') input_rails_rect = [rvdd_samp_m5] [rvdd_samp_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAMP_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_samp, netnames=['VDDSAMP'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_samp = 'route_M5_M6_thick_temp_tisar_samp_vss' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_samp, xy=vsssamp_xy, xy_grid_type='ygrid') input_rails_rect = [rvss_samp_m5] [rvss_samp_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAMP_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_samp, netnames=['VSS:'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) ''' rg_m5m6_clkd='route_M5_M6_thick_temp_tisar_clkd' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_clkd, xy=vddclkd_xy + vssclkd_xy, xy_grid_type='ygrid') input_rails_rect = [rvdd_samp_m5, rvss_samp_m5] [rvdd_clkd_m6, rvss_clkd_m6] = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_CLKD_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_clkd, netnames=['VDDSAMP', 'VSS:'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) ''' print(num_space_sar, num_space_samp) yamlfile_output = "adc_sar_size.yaml" #write to file with open(yamlfile_output, 'r') as stream: outdict = yaml.load(stream) outdict['num_space_sar'] = num_space_sar outdict['num_space_samp'] = num_space_samp with open(yamlfile_output, 'w') as stream: yaml.dump(outdict, stream)
def generate_tisaradc_dcap(laygen, objectname_pfix, templib_logic, placement_grid, routing_grid_m2m3, routing_grid_m3m4, rg_m3m4_basic_thick, rg_m4m5_thick, num_bits=9, origin=np.array([0, 0])): """generate tisaradc """ inv_name = 'inv_2x' tap_name = 'tap' dcap_unit_name = 'tisaradc_dcap_unit' pg = placement_grid rg_m2m3 = routing_grid_m2m3 rg_m3m4 = routing_grid_m3m4 # 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('tisaradc_dcap_unit', workinglib).xy[1][0] + \ laygen.templates.get_template('tap', templib_logic).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 devname_bnd_left = [] devname_bnd_right = [] transform_bnd_left = [] transform_bnd_right = [] num_row = num_bits * 4 for i in range(num_row): if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] [bnd_bottom, bnd_top, bnd_left, bnd_right] = 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=np.array([0, 0])) #Calculate layout size array_origin = origin + laygen.get_template_xy( name='boundary_bottomleft', gridname=pg, libname=utemplib) tapr_origin = np.array([laygen.get_template_xy(name='tisaradc_dcap_unit', gridname=pg, libname=workinglib)[0], 0]) \ + np.array([0, laygen.get_template_xy(name='boundary_bottomleft', gridname=pg, libname=utemplib)[1]]) \ + np.array([laygen.get_template_xy(name='boundary_bottomleft', gridname=pg, libname=utemplib)[0], 0]) \ + np.array([laygen.get_template_xy(name=tap_name, gridname=pg, libname=templib_logic)[0], 0]) # placement itapl = [] idcap = [] for i in range(num_row): if i % 2 == 0: tf = 'R0' else: tf = 'MX' if i == 0: itapl.append( laygen.relplace(name="I" + objectname_pfix + 'ITAPL' + str(i), templatename=tap_name, gridname=pg, refinstname=None, xy=array_origin, template_libname=templib_logic)) else: itapl.append( laygen.relplace(name="I" + objectname_pfix + 'ITAPL' + str(i), templatename=tap_name, gridname=pg, refinstname=itapl[-1].name, template_libname=templib_logic, direction='top', transform=tf)) idcap.append( laygen.relplace(name="I" + objectname_pfix + 'Idcap' + str(i), templatename=dcap_unit_name, gridname=pg, refinstname=itapl[-1].name, template_libname=workinglib, direction='right', transform=tf)) itapr = [] for i in range(num_row): if i % 2 == 0: tf = 'R0' else: tf = 'MX' if i == 0: itapr.append( laygen.relplace(name="I" + objectname_pfix + 'ITAPR' + str(i), templatename=tap_name, gridname=pg, refinstname=None, xy=tapr_origin, template_libname=templib_logic)) else: itapr.append( laygen.relplace(name="I" + objectname_pfix + 'ITAPR' + str(i), templatename=tap_name, gridname=pg, refinstname=itapr[-1].name, template_libname=templib_logic, direction='top', transform=tf)) # pins pdict = laygen.get_inst_pin_xy(None, None, rg_m3m4_basic_thick) # laygen.pin(name='I', layer=laygen.layers['pin'][4], xy=laygen.get_inst_pin_xy(idcap[-1].name, 'I', rg_m3m4_basic_thick), # gridname=rg_m3m4_basic_thick) # power pin pwr_dim = laygen.get_template_xy(name=itapl[0].cellname, gridname=rg_m2m3, libname=itapl[0].libname) rvddl_m3 = [] rvssl_m3 = [] rvddr_m3 = [] rvssr_m3 = [] for i in range(0, int(pwr_dim[0] / 2)): rvddl_m3.append( laygen.route(None, laygen.layers['metal'][3], xy0=np.array([2 * i + 1, 0]), xy1=np.array([2 * i + 1, 0]), gridname0=rg_m2m3, refinstname0=itapl[0].name, refpinname0='VSS', refinstindex0=np.array([0, 0]), refinstname1=itapl[num_row - 1].name, refpinname1='VSS', refinstindex1=np.array([0, 0]))) rvssl_m3.append( laygen.route(None, laygen.layers['metal'][3], xy0=np.array([2 * i + 2, 0]), xy1=np.array([2 * i + 2, 0]), gridname0=rg_m2m3, refinstname0=itapl[0].name, refpinname0='VSS', refinstindex0=np.array([0, 0]), refinstname1=itapl[num_row - 1].name, refpinname1='VSS', refinstindex1=np.array([0, 0]))) for j in range(num_row): laygen.via(None, xy=np.array([2 * i + 1, 0]), gridname=rg_m2m3, refinstname=itapl[j].name, refpinname='VDD') laygen.via(None, xy=np.array([2 * i + 2, 0]), gridname=rg_m2m3, refinstname=itapl[j].name, refpinname='VSS') # laygen.pin(name = 'VDDL'+str(i), layer = laygen.layers['pin'][3], refobj = rvddl_m3[-1], gridname=rg_m2m3, netname='VDD') # laygen.pin(name = 'VSSL'+str(i), layer = laygen.layers['pin'][3], refobj = rvssl_m3[-1], gridname=rg_m2m3, netname='VSS') rvddr_m3.append( laygen.route(None, laygen.layers['metal'][3], xy0=np.array([2 * i + 1, 0]), xy1=np.array([2 * i + 1, 0]), gridname0=rg_m2m3, refinstname0=itapr[0].name, refpinname0='VSS', refinstindex0=np.array([0, 0]), refinstname1=itapr[num_row - 1].name, refpinname1='VSS', refinstindex1=np.array([0, 0]))) rvssr_m3.append( laygen.route(None, laygen.layers['metal'][3], xy0=np.array([2 * i + 2, 0]), xy1=np.array([2 * i + 2, 0]), gridname0=rg_m2m3, refinstname0=itapr[0].name, refpinname0='VSS', refinstindex0=np.array([0, 0]), refinstname1=itapr[num_row - 1].name, refpinname1='VSS', refinstindex1=np.array([0, 0]))) for j in range(num_row): laygen.via(None, xy=np.array([2 * i + 1, 0]), gridname=rg_m2m3, refinstname=itapr[j].name, refpinname='VDD') laygen.via(None, xy=np.array([2 * i + 2, 0]), gridname=rg_m2m3, refinstname=itapr[j].name, refpinname='VSS') # laygen.pin(name = 'VDDR'+str(i), layer = laygen.layers['pin'][3], refobj = rvddr_m3[-1], gridname=rg_m2m3, netname='VDD') # laygen.pin(name = 'VSSR'+str(i), layer = laygen.layers['pin'][3], refobj = rvssr_m3[-1], gridname=rg_m2m3, netname='VSS') #m4 input_rails_rect = [rvddl_m3, rvssl_m3] rvddl_m4, rvssl_m4 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_basic_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=2, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) x1_phy = laygen.get_xy(obj =bnd_right[0])[0]\ +laygen.get_xy(obj =bnd_right[0].template)[0] x1 = laygen.grids.get_absgrid_x(rg_m3m4_basic_thick, x1_phy) input_rails_rect = [rvddr_m3, rvssr_m3] rvddr_m4, rvssr_m4 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_basic_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=x1 - 2, offset_start_index=0, offset_end_index=0) #m5 input_rails_rect = [rvddl_m4, rvssl_m4] rvddl_m5, rvssl_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M5_', layer=laygen.layers['pin'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', 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) y1_phy = laygen.get_xy(obj =bnd_top[0])[1]\ +laygen.get_xy(obj =bnd_top[0].template)[1] y1 = laygen.grids.get_absgrid_x(rg_m4m5_thick, y1_phy) input_rails_rect = [rvddr_m4, rvssr_m4] rvddr_m5, rvssr_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M5_', layer=laygen.layers['pin'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', 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_cap_wbnd(laygen, objectname_pfix, workinglib, cap_name, placement_grid, m=1, shape=np.array([1, 1]), origin=np.array([0, 0])): cap_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) icap = [] for i in range(m): if i == 0: icap.append( laygen.place(name="I" + objectname_pfix + 'SP0', templatename=cap_name, gridname=pg, xy=cap_origin, shape=shape, template_libname=workinglib)) else: if i % 2 == 0: icap.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i), templatename=cap_name, gridname=pg, refinstname=icap[-1].name, shape=shape, template_libname=workinglib, direction='top')) else: icap.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(i), templatename=cap_name, gridname=pg, refinstname=icap[-1].name, shape=shape, template_libname=workinglib, direction='top', transform='MX')) xy0 = laygen.get_template_size( name=cap_name, gridname=pg, libname=workinglib) * shape xsp = xy0[0] #ysp=xy0[1] m_bnd = int(xsp / laygen.get_template_size('boundary_bottom', gridname=pg)[0]) devname_left = [] devname_right = [] transform_left = [] transform_right = [] for i in range(m): if i % 2 == 0: devname_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_left += ['R0', 'MX'] transform_right += ['R0', 'MX'] else: devname_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_left += ['MX', 'R0'] transform_right += ['MX', 'R0'] [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_left, transform_left=transform_left, devname_right=devname_right, transform_right=transform_right, origin=origin) pdict_m3m4_thick = laygen.get_inst_pin_coord(None, None, rg_m3m4_thick) for i in range(int((m + 1) / 2)): pxyvdd = pdict_m3m4_thick[icap[i * 2].name]['VDD'] pxyvdd[1] = pxyvdd[0] + (pxyvdd[1] - pxyvdd[0]) * shape pxyvss = pdict_m3m4_thick[icap[i * 2].name]['VSS'] pxyvss[1] = pxyvss[0] + (pxyvss[1] - pxyvss[0]) * shape laygen.pin('VDD' + str(i), laygen.layers['pin'][4], pdict_m3m4_thick[icap[i * 2].name]['VDD'], gridname=rg_m3m4_thick, netname='VDD') laygen.pin('VSS' + str(i), laygen.layers['pin'][4], pdict_m3m4_thick[icap[i * 2].name]['VSS'], gridname=rg_m3m4_thick, netname='VSS') cap_template = laygen.templates.get_template(cap_name, workinglib) cap_pins = cap_template.pins if 'I' in cap_pins: if m == 1: laygen.pin('I', laygen.layers['pin'][4], pdict_m3m4_thick[icap[i].name]['I'], gridname=rg_m3m4_thick) else: for i in range(int(m)): laygen.pin('I<' + str(i) + '>', laygen.layers['pin'][4], pdict_m3m4_thick[icap[i].name]['I'], gridname=rg_m3m4_thick)
def generate_tisaradc_dcap_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 = 'tisaradc_dcap' sar_name = 'sar_wsamp_bb_doubleSA' ret_name = 'adc_retimer' tisar_name = 'tisaradc_splash' 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=tisar_name, gridname=None, libname=workinglib)[0] dcap_x = laygen.get_template_xy(name=r2r_name, gridname=None, libname=workinglib)[0] num_hori = int(x1_phy / dcap_x) # placement irdac = laygen.relplace(name="I" + objectname_pfix + 'Idcap', templatename=r2r_name, gridname=pg, refinstname=None, xy=origin, shape=[num_hori, 1], template_libname=workinglib) # 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.name]: if p.startswith('VDD'): r0 = laygen.route( None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac.name, p, rg_m5m6_thick, index=np.array([i, 0]))[0], xy1=laygen.get_inst_pin_xy(irdac.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.name]: if p.startswith('VSS'): r0 = laygen.route( None, laygen.layers['metal'][5], xy0=laygen.get_inst_pin_xy(irdac.name, p, rg_m5m6_thick, index=np.array([i, 0]))[0], xy1=laygen.get_inst_pin_xy(irdac.name, p, rg_m5m6_thick, index=np.array([i, 0]))[1], gridname0=rg_m5m6_thick) rvss_m5.append(r0) # m6 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=None)
def generate_sarabe_dualdelay(laygen, objectname_pfix, workinglib, placement_grid, routing_grid_m2m3, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, routing_grid_m4m5, num_bits=9, origin=np.array([0, 0])): """generate sar backend """ pg = placement_grid rg_m2m3 = routing_grid_m2m3 rg_m3m4_thick = routing_grid_m3m4_thick rg_m4m5_thick = routing_grid_m4m5_thick rg_m5m6_thick = routing_grid_m5m6_thick rg_m4m5 = routing_grid_m4m5 #sarfsm_name = 'sarfsm_'+str(num_bits)+'b' sarfsm_name = 'sarfsm' #_'+str(num_bits)+'b' #sarlogic_name = 'sarlogic_wret_v2_array_'+str(num_bits)+'b' sarlogic_name = 'sarlogic_wret_v2_array_bb_pe' #_'+str(num_bits)+'b' sarclkgen_name = 'sarclkgen_static' #sarret_name = 'sarret_wckbuf_'+str(num_bits)+'b' sarret_name = 'sarret_wckbuf' #_'+str(num_bits)+'b' #space_name = 'space_dcap_nmos' space_name = 'space' xy0 = laygen.get_template_size(name=space_name, gridname=pg, libname=workinglib) xsp = xy0[0] ysp = xy0[1] # placement core_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) isp = [] devname_bnd_left = [] devname_bnd_right = [] transform_bnd_left = [] transform_bnd_right = [] #additional space for routing area isp.append( laygen.place(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, xy=core_origin, transform='R0', template_libname=workinglib)) refi = isp[-1].name isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += [ 'nmos4_fast_left', 'pmos4_fast_left', 'pmos4_fast_left', 'nmos4_fast_left' ] devname_bnd_right += [ 'nmos4_fast_right', 'pmos4_fast_right', 'pmos4_fast_right', 'nmos4_fast_right' ] transform_bnd_left += ['R0', 'MX', 'R0', 'MX'] transform_bnd_right += ['R0', 'MX', 'R0', 'MX'] #ret iret = laygen.relplace(name="I" + objectname_pfix + 'RET0', templatename=sarret_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = iret.name yret = int( laygen.get_template_size( name=sarret_name, gridname=pg, libname=workinglib)[1] / ysp) for i in range(yret): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion if number of rows is odd if not yret % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #fsm ifsm = laygen.relplace(name="I" + objectname_pfix + 'FSM0', templatename=sarfsm_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = ifsm.name yfsm = int( laygen.get_template_size( name=sarfsm_name, gridname=pg, libname=workinglib)[1] / ysp) for i in range(yfsm): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion if number of rows is odd if not yfsm % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # sarlogic isl = laygen.relplace(name="I" + objectname_pfix + 'SL0', templatename=sarlogic_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = isl.name ysl = int( laygen.get_template_size( name=sarlogic_name, gridname=pg, libname=workinglib)[1] / ysp) for i in range(ysl): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion 2 if number of rows is even, 1 if odd if ysl % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='R0', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #clkdelay & clkgen ickg = laygen.relplace(name="I" + objectname_pfix + 'CKG0', templatename=sarclkgen_name, gridname=pg, refinstname=refi, direction='top', transform='R0', template_libname=workinglib) refi = ickg.name yck = laygen.get_template_size( name=sarclkgen_name, gridname=pg, libname=workinglib)[1] / ysp for i in range(int(yck)): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion if number of rows is odd if not yck % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # boundaries m_bnd = int(xsp / laygen.get_template_size('boundary_bottom', gridname=pg)[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) #route #reference coordinates pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4) pdict_m4m5 = laygen.get_inst_pin_xy(None, None, rg_m4m5) pdict_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6) x_right = laygen.get_inst_xy(name=ifsm.name, gridname=rg_m5m6)[0]\ +laygen.get_template_size(name=ifsm.cellname, gridname=rg_m5m6, libname=workinglib)[0] - 1 y_top = laygen.get_inst_xy(name=ickg.name, gridname=rg_m5m6)[1] - 1 xysl = laygen.get_inst_xy(name=isl.name, gridname=rg_m5m6) xyfsm = laygen.get_inst_xy(name=ifsm.name, gridname=rg_m5m6) xyret = laygen.get_inst_xy(name=iret.name, gridname=rg_m5m6) # rst signal route x0 = pdict_m4m5[ickg.name]['EXTSEL_CLK'][0][0] # very important because it sets the timing margin # ckg to sl [rh0, rrst0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['RST'][0], pdict_m5m6[isl.name]['RST'][0], pdict_m5m6[ickg.name]['RST'][0][0] + 2, rg_m4m5) [rh0, rrst1, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['RST'][0], pdict_m5m6[isl.name]['RST'][0], pdict_m5m6[ickg.name]['RST'][0][0] + 4, rg_m4m5) #[rh0, rrst2, rh1] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_m5m6[ickg.name]['RST'][0], # pdict_m5m6[isl.name]['RST'][0], # pdict_m5m6[ickg.name]['RST'][0][0]+6, rg_m4m5) # ckg to fsm [rh0, rrst0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['RST'][0], pdict_m5m6[ifsm.name]['RST'][0], pdict_m5m6[ickg.name]['RST'][0][0] + 2, rg_m4m5) [rh0, rrst1, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['RST'][0], pdict_m5m6[ifsm.name]['RST'][0], pdict_m5m6[ickg.name]['RST'][0][0] + 4, rg_m4m5) #[rh0, rrst2, rh1] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_m5m6[ickg.name]['RST'][0], # pdict_m5m6[ifsm.name]['RST'][0], # pdict_m5m6[ickg.name]['RST'][0][0]+6, rg_m4m5) # ckg to ret [rh0, rrst0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['RST'][0], pdict_m5m6[iret.name]['CLK'][0], pdict_m5m6[ickg.name]['RST'][0][0] + 2, rg_m4m5) [rh0, rrst1, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['RST'][0], pdict_m5m6[iret.name]['CLK'][0], pdict_m5m6[ickg.name]['RST'][0][0] + 4, rg_m4m5) #[rh0, rrst2, rh1] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_m5m6[ickg.name]['RST'][0], # pdict_m5m6[iret.name]['CLK'][0], # pdict_m5m6[ickg.name]['RST'][0][0]+6, rg_m4m5) # rst output to final retimer rrstout0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m5m6[iret.name]['CLKO0'][0], xy1=np.array( [pdict_m5m6[iret.name]['CLKO0'][0][0], 0]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rrstout0, rg_m4m5, 'RSTOUT0', laygen.layers['pin'][5], size=6, direction='bottom', netname='RSTOUT') rrstout1 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m5m6[iret.name]['CLKO1'][0], xy1=np.array( [pdict_m5m6[iret.name]['CLKO1'][0][0], 0]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rrstout1, rg_m4m5, 'RSTOUT1', laygen.layers['pin'][5], size=6, direction='bottom', netname='RSTOUT') # clk input laygen.boundary_pin_from_rect(rrst0, rg_m5m6, 'RST0', laygen.layers['pin'][5], size=6, direction='top', netname='RST') laygen.boundary_pin_from_rect(rrst1, rg_m5m6, 'RST1', laygen.layers['pin'][5], size=6, direction='top', netname='RST') #laygen.boundary_pin_from_rect(rrst2, rg_m5m6, 'RST2' , laygen.layers['pin'][5], size=6, direction='top', netname='RST') # sarclk signal route # ckgen to fsm rh0, rv0, rh1 = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['CLKO'][0], pdict_m4m5[ifsm.name]['CLK'][0], pdict_m4m5[ickg.name]['CLKO'][1][0] + 2, rg_m4m5) # ckgen to fsm #2 (to reduce route resistance) rh0, rv0, rh1 = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['CLKO'][0], pdict_m4m5[ifsm.name]['CLK'][0], pdict_m4m5[ickg.name]['CLKO'][1][0] + 4, rg_m4m5) ## ckgen to fsm #rh0, rv0, rh1 = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_m4m5[ickg.name]['CLKO'][0], pdict_m4m5[ifsm.name]['CLK'][0], # pdict_m4m5[isl.name]['RETO<'+str(num_bits-2)+'>'][1][0]+9-4-1-3, rg_m4m5) ## ckgen to fsm #2 (to reduce route resistance) #rh0, rv0, rh1 = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_m4m5[ickg.name]['CLKO'][0], pdict_m4m5[ifsm.name]['CLK'][0], # pdict_m4m5[isl.name]['RETO<'+str(num_bits-2)+'>'][1][0]+11-4-1-3, rg_m4m5) # ckgen to sl route # saopb/saomb [rh0, rsaop0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['SAOP'][0], pdict_m5m6[isl.name]['SAOP'][0], pdict_m5m6[ickg.name]['SAOP'][0][0] + 0, rg_m4m5) [rh0, rsaom0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['SAOM'][0], pdict_m5m6[isl.name]['SAOM'][0], pdict_m5m6[ickg.name]['SAOM'][0][0] + 1, rg_m4m5) #equalize vertical route for pin generation rsaop0_xy = laygen.get_rect_xy(rsaop0.name, rg_m4m5, sort=True) rsaom0_xy = laygen.get_rect_xy(rsaom0.name, rg_m4m5, sort=True) rsao_y0 = min((rsaop0_xy[0][1], rsaom0_xy[0][1])) rsao_y1 = max((rsaop0_xy[1][1], rsaom0_xy[1][1])) rsaop0 = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([rsaop0_xy[0][0], rsao_y0]), xy1=np.array([rsaop0_xy[1][0], rsao_y1]), gridname0=rg_m4m5) rsaom0 = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([rsaom0_xy[0][0], rsao_y0]), xy1=np.array([rsaom0_xy[1][0], rsao_y1]), gridname0=rg_m4m5) # fsm to sl route # sb for i in range(num_bits): [rv0, rh0, rv1 ] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[ifsm.name]['SB<' + str(i) + '>'][0], pdict_m5m6[isl.name]['SB<' + str(i) + '>'][0], xysl[1] - i - 1, rg_m5m6) # zp/zm/zmid for i in range(num_bits): rzp0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m4m5[isl.name]['ZP<' + str(i) + '>'][0], xy1=pdict_m4m5[isl.name]['ZP<' + str(i) + '>'][0] + np.array([0, 4]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rzp0, rg_m5m6, 'ZP<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='top') rzm0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m4m5[isl.name]['ZM<' + str(i) + '>'][0], xy1=pdict_m4m5[isl.name]['ZM<' + str(i) + '>'][0] + np.array([0, 4]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rzm0, rg_m5m6, 'ZM<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='top') rzmid0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5[isl.name]['ZMID<' + str(i) + '>'][0], xy1=pdict_m4m5[isl.name]['ZMID<' + str(i) + '>'][0] + np.array([0, 4]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(rzmid0, rg_m5m6, 'ZMID<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='top') # zmid to short #rh0, rv0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], # pdict_m4m5[ickg.name]['SHORTB'][0], # pdict_m4m5[isl.name]['ZMID<5>'][0], rg_m4m5) rh0, rv0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['SHORTB'][0], pdict_m4m5[isl.name]['ZMID<' + str(max(0, num_bits - 3)) + '>'][0], rg_m4m5) # ckdsel for i in range(2): rh0, rclkdsel0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['SEL<' + str(i) + '>'][0], np.array([ pdict_m4m5[ickg.name]['SEL<' + str(i) + '>'][1][0] + 1 + i + 2 + 2 + 1, 0 ]), rg_m4m5) laygen.boundary_pin_from_rect(rclkdsel0, rg_m4m5, 'CKDSEL0<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='bottom') rh0, rclkdsel1 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['SEL<2>'][0], np.array( [pdict_m4m5[ickg.name]['SEL<2>'][1][0] + 1 + 3 + 2 + 2 + 1, 0]), rg_m4m5) laygen.boundary_pin_from_rect(rclkdsel1, rg_m4m5, 'CKDSEL1<0>', laygen.layers['pin'][5], size=6, direction='bottom') #ckdsel dummy xy0 = laygen.get_rect_xy(name=rclkdsel0.name, gridname=rg_m4m5, sort=True) rclkdsel1 = laygen.route(None, laygen.layers['metal'][5], xy0=xy0[0] + np.array([3, 0]), xy1=xy0[0] + np.array([3, 4]), gridname0=rg_m4m5) laygen.boundary_pin_from_rect(rclkdsel1, rg_m4m5, 'CKDSEL1<1>', laygen.layers['pin'][5], size=6, direction='bottom') # SAOP/SAOM laygen.boundary_pin_from_rect(rsaop0, rg_m4m5, 'SAOP', laygen.layers['pin'][5], size=6, direction='top') laygen.boundary_pin_from_rect(rsaom0, rg_m4m5, 'SAOM', laygen.layers['pin'][5], size=6, direction='top') # extclk, extsel_clk rh0, rextsel_clk0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['EXTSEL_CLK'][0], np.array([x0 - 2, 0]), rg_m4m5) #np.array([x0+13+3, 0]), rg_m4m5) laygen.boundary_pin_from_rect(rextsel_clk0, rg_m4m5, 'EXTSEL_CLK', laygen.layers['pin'][5], size=6, direction='bottom') # fsm to ret (data) for i in range(num_bits): if i % 2 == 0: #even channel [rv0, rh0, rv1] = laygen.route_vhv( laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[isl.name]['RETO<' + str(i) + '>'][0], pdict_m5m6[iret.name]['IN<' + str(i) + '>'][0], xyfsm[1] - int(i / 2) * 2 + 4, rg_m5m6) else: [rv0, rh0, rv1] = laygen.route_vhv( laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[isl.name]['RETO<' + str(i) + '>'][0], pdict_m5m6[iret.name]['IN<' + str(i) + '>'][0], xyfsm[1] - int(i / 2) * 2 - int(num_bits / 2) * 2 - 2, rg_m5m6) # adcout for i in range(num_bits): radco0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5[iret.name]['OUT<' + str(i) + '>'][0], xy1=np.array( [pdict_m4m5[iret.name]['OUT<' + str(i) + '>'][0][0], 0]), gridname0=rg_m5m6) laygen.boundary_pin_from_rect(radco0, rg_m4m5, 'ADCOUT<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='bottom') # probe outputs laygen.pin(name='PHI0', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['PHI0'], gridname=rg_m4m5) laygen.pin(name='UP', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['UP'], gridname=rg_m4m5) laygen.pin(name='DONE', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['DONE'], gridname=rg_m4m5) laygen.pin(name='SARCLK', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['CLKO'], gridname=rg_m4m5) laygen.pin(name='SARCLKB', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['CLKOB'], gridname=rg_m4m5) for i in range(num_bits): laygen.pin(name='SB<' + str(i) + '>', layer=laygen.layers['pin'][5], xy=pdict_m5m6[isl.name]['SB<' + str(i) + '>'], gridname=rg_m5m6) # vdd/vss # m3 rvddl_m3 = [] rvssl_m3 = [] rvddr_m3 = [] rvssr_m3 = [] xret_center = int( laygen.get_template_size( name=sarret_name, gridname=rg_m3m4_thick, libname=workinglib)[0] / 2) for p in pdict_m3m4[iret.name]: if p.startswith('VDD'): r0 = laygen.route(None, laygen.layers['metal'][3], xy0=pdict_m3m4[iret.name][p][0], xy1=pdict_m3m4[isp[-1].name][p][0], gridname0=rg_m3m4) if pdict_m3m4[iret.name][p][0][0] < xret_center: rvddl_m3.append(r0) else: rvddr_m3.append(r0) for p in pdict_m3m4[iret.name]: if p.startswith('VSS'): r0 = laygen.route(None, laygen.layers['metal'][3], xy0=pdict_m3m4[iret.name][p][0], xy1=pdict_m3m4[isp[-1].name][p][0], gridname0=rg_m3m4) if pdict_m3m4[iret.name][p][0][0] < xret_center: rvssl_m3.append(r0) else: rvssr_m3.append(r0) #m4 input_rails_rect = [rvddl_m3, rvssl_m3] rvddl_m4, rvssl_m4 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, offset_start_index=2, offset_end_index=-8) x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m3m4_thick, libname=utemplib)[0] input_rails_rect = [rvddr_m3, rvssr_m3] rvddr_m4, rvssr_m4 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=x1, offset_start_index=2, offset_end_index=-8) #additional m4 routes inst_exclude = [isp[0], isp[1], iret, ifsm, isl, ickg, isp[-1], isp[-2]] x0 = laygen.get_inst_xy(name=bnd_left[0].name, gridname=rg_m3m4_thick)[0] y0 = laygen.get_inst_xy(name=bnd_left[0].name, gridname=rg_m3m4_thick)[1] x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m3m4_thick, libname=utemplib)[0] y1 = laygen.get_inst_xy(name=bnd_left[-1].name, gridname=rg_m3m4_thick)[1] for i in range(y1 - y0): #check if y is not in the exclude area trig = 1 for iex in inst_exclude: if iex.transform == 'MX': yex0 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1]-1\ -laygen.get_template_size(name=iex.cellname, gridname=rg_m3m4_thick, libname=workinglib)[1] yex1 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1] + 1 else: yex0 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1] - 1 yex1 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1]+1\ +laygen.get_template_size(name=iex.cellname, gridname=rg_m3m4_thick, libname=workinglib)[1] if y0 + i > yex0 and y0 + i < yex1: #exclude trig = 0 if trig == 1: r0 = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x0, y0 + i]), xy1=np.array([x1, y0 + i]), gridname0=rg_m3m4_thick) #m5 y1 = laygen.get_inst_xy(name=bnd_top[0].name, gridname=rg_m4m5_thick)[1]\ +laygen.get_template_size(name=bnd_top[0].cellname, gridname=rg_m4m5_thick)[1] input_rails_rect = [rvddl_m4, rvssl_m4] rvddl_m5, rvssl_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_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=0, overwrite_end_coord=y1, offset_start_index=1, offset_end_index=0) input_rails_rect = [rvddr_m4, rvssr_m4] rvddr_m5, rvssr_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_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=0, overwrite_end_coord=y1, offset_start_index=1, offset_end_index=0) #m6 input_rails_rect = [rvddl_m5, rvssl_m5] rvddl_m6, rvssl_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, offset_start_index=1, offset_end_index=-1) x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m5m6_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m5m6_thick, libname=utemplib)[0] x1_phy = laygen.get_inst_xy(name=bnd_right[0].name)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, libname=utemplib)[0] input_rails_rect = [rvddr_m5, rvssr_m5] rvddr_m6, rvssr_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=x1, offset_start_index=1, offset_end_index=-1) #trimming for r in rvddr_m6: r.xy1[0] = x1_phy for r in rvssr_m6: r.xy1[0] = x1_phy #addtional m6 routes rvdd_m6 = [] rvss_m6 = [] #inst_reference=[isp[0], isp[1], iret,ifsm,isl] inst_reference = [ifsm, isl] inst_reference_offset0 = [3, 1] inst_reference_offset1 = [4, 7] #num_route=[10,10] num_route = [] for i, inst in enumerate(inst_reference): num_route.append( laygen.get_template_size(name=inst.cellname, gridname=rg_m5m6_thick, libname=workinglib)[1] - 2) x0 = laygen.get_inst_xy(name=bnd_left[0].name, gridname=rg_m5m6_thick)[0] x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m5m6_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m5m6_thick, libname=utemplib)[0] n_vdd_m6 = 0 #number for m6 wires n_vss_m6 = 0 #number for m6 wires for i, inst in enumerate(inst_reference): for j in range(inst_reference_offset0[i], num_route[i] - inst_reference_offset1[i]): if i == 0: y0 = laygen.get_inst_xy(name=inst.name, gridname=rg_m5m6_thick)[1] + 1 r0 = laygen.route(None, laygen.layers['metal'][6], xy0=np.array([x0, y0 + j]), xy1=np.array([x1, y0 + j]), gridname0=rg_m5m6_thick) r0.xy1[0] = x1_phy else: y0 = laygen.get_inst_xy(name=inst.name, gridname=rg_m5m6_thick)[1] + 1 r0 = laygen.route(None, laygen.layers['metal'][6], xy0=np.array([x0, y0 + j]), xy1=np.array([x1, y0 + j]), gridname0=rg_m5m6_thick) r0.xy1[0] = x1_phy if j % 2 == 0: rvdd_m6.append(r0) xy0 = laygen.get_rect_xy(name=r0.name, gridname=rg_m5m6_thick) laygen.pin(name='VDD_M6' + str(n_vdd_m6), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDD') n_vdd_m6 += 1 else: rvss_m6.append(r0) xy0 = laygen.get_rect_xy(name=r0.name, gridname=rg_m5m6_thick) laygen.pin(name='VSS_M6' + str(n_vss_m6), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS') n_vss_m6 += 1 # VBB rvbb_m3 = [] for p in pdict_m3m4[isl.name]: if p.startswith('VBB'): laygen.pin(name=str(p), layer=laygen.layers['pin'][3], xy=pdict_m3m4[isl.name][p], gridname=rg_m3m4, netname='VBB')
def generate_sarabe_dualdelay(laygen, objectname_pfix, workinglib, placement_grid, routing_grid_m2m3, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, routing_grid_m4m5, num_bits=9, origin=np.array([0, 0])): """generate sar backend """ pg = placement_grid rg_m2m3 = routing_grid_m2m3 rg_m3m4_thick = routing_grid_m3m4_thick rg_m4m5_thick = routing_grid_m4m5_thick rg_m5m6_thick = routing_grid_m5m6_thick rg_m4m5 = routing_grid_m4m5 sarfsm_name = 'sarfsm_' + str(num_bits) + 'b' sarlogic_name = 'sarlogic_wret_array_' + str(num_bits) + 'b' sarclkdelay_name = 'sarclkdelay_compact_dual' sarclkgen_name = 'sarclkgen_static' sarret_name = 'sarret_' + str(num_bits) + 'b' space_name = 'space' xy0 = laygen.get_template_size(name=space_name, gridname=pg, libname=workinglib) xsp = xy0[0] ysp = xy0[1] # placement core_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) isp = [] devname_bnd_left = [] devname_bnd_right = [] transform_bnd_left = [] transform_bnd_right = [] #additional space for routing area isp.append( laygen.place(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, xy=core_origin, transform='R0', template_libname=workinglib)) refi = isp[-1].name isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += [ 'nmos4_fast_left', 'pmos4_fast_left', 'pmos4_fast_left', 'nmos4_fast_left' ] devname_bnd_right += [ 'nmos4_fast_right', 'pmos4_fast_right', 'pmos4_fast_right', 'nmos4_fast_right' ] transform_bnd_left += ['R0', 'MX', 'R0', 'MX'] transform_bnd_right += ['R0', 'MX', 'R0', 'MX'] #ret iret = laygen.relplace(name="I" + objectname_pfix + 'RET0', templatename=sarret_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = iret.name yret = int( laygen.get_template_size( name=sarret_name, gridname=pg, libname=workinglib)[1] / ysp) for i in range(yret): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion if number of rows is odd if not yret % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #fsm ifsm = laygen.relplace(name="I" + objectname_pfix + 'FSM0', templatename=sarfsm_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = ifsm.name yfsm = int( laygen.get_template_size( name=sarfsm_name, gridname=pg, libname=workinglib)[1] / ysp) for i in range(yfsm): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion if number of rows is odd if not yfsm % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #additional space for routing area isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='R0', template_libname=workinglib)) refi = isp[-1].name isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += [ 'nmos4_fast_left', 'pmos4_fast_left', 'pmos4_fast_left', 'nmos4_fast_left' ] devname_bnd_right += [ 'nmos4_fast_right', 'pmos4_fast_right', 'pmos4_fast_right', 'nmos4_fast_right' ] transform_bnd_left += ['R0', 'MX', 'R0', 'MX'] transform_bnd_right += ['R0', 'MX', 'R0', 'MX'] # sarlogic isl = laygen.relplace(name="I" + objectname_pfix + 'SL0', templatename=sarlogic_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = isl.name ysl = int( laygen.get_template_size( name=sarlogic_name, gridname=pg, libname=workinglib)[1] / ysp) for i in range(ysl): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] # space insertion if number of rows is odd if not ysl % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #clkdelay & clkgen ickd = laygen.relplace(name="I" + objectname_pfix + 'CKD0', templatename=sarclkdelay_name, gridname=pg, refinstname=refi, direction='top', template_libname=workinglib) refi = ickd.name ickg = laygen.relplace(name="I" + objectname_pfix + 'CKG0', templatename=sarclkgen_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib) refi = ickg.name # space insertion if number of rows is odd yck=(laygen.get_template_size(name=sarclkdelay_name, gridname=pg, libname=workinglib)[1]+\ laygen.get_template_size(name=sarclkgen_name, gridname=pg, libname=workinglib)[1])/ysp for i in range(int(yck)): #boundary cells if i % 2 == 0: devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] if not int(yck / ysp) % 2 == 0: isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] #additional space for routing area isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='R0', template_libname=workinglib)) refi = isp[-1].name isp.append( laygen.relplace(name="I" + objectname_pfix + 'SP' + str(len(isp)), templatename=space_name, gridname=pg, refinstname=refi, direction='top', transform='MX', template_libname=workinglib)) refi = isp[-1].name devname_bnd_left += [ 'nmos4_fast_left', 'pmos4_fast_left', 'pmos4_fast_left', 'nmos4_fast_left' ] devname_bnd_right += [ 'nmos4_fast_right', 'pmos4_fast_right', 'pmos4_fast_right', 'nmos4_fast_right' ] transform_bnd_left += ['R0', 'MX', 'R0', 'MX'] transform_bnd_right += ['R0', 'MX', 'R0', 'MX'] # boundaries m_bnd = int(xsp / laygen.get_template_size('boundary_bottom', gridname=pg)[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) #route #reference coordinates 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) x_right = laygen.get_inst_xy(name=ifsm.name, gridname=rg_m5m6)[0]\ +laygen.get_template_size(name=ifsm.cellname, gridname=rg_m5m6, libname=workinglib)[0] - 1 y_top = laygen.get_inst_xy(name=ickg.name, gridname=rg_m5m6)[1] - 1 xysl = laygen.get_inst_xy(name=isl.name, gridname=rg_m5m6) xyfsm = laygen.get_inst_xy(name=ifsm.name, gridname=rg_m5m6) xyret = laygen.get_inst_xy(name=iret.name, gridname=rg_m5m6) # rst signal route # very important because it sets the timing margin # ckd to sl rh0, rh0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickd.name]['RST'][0], pdict_m4m5[isl.name]['RST'][0], rg_m4m5) # fsm to sl [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[ifsm.name]['RST'][0], pdict_m5m6[isl.name]['RST'][0], xyfsm[1] - num_bits - 2, rg_m5m6) # ckg to sl route rh0, rrst0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['RST'][0], pdict_m4m5[isl.name]['RST'][0], rg_m4m5) # fsm to ret (rst) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[isl.name]['RST'][0], pdict_m5m6[iret.name]['CLK'][0], xyfsm[1] - num_bits - 2, rg_m5m6) # clk output to final retimer #rrstout0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6[ifsm.name]['RST'][0], # xy1=np.array([pdict_m5m6[ifsm.name]['RST'][0][0], 0]), gridname0=rg_m5m6) rrstout0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m5m6[isl.name]['RST'][0], xy1=np.array( [pdict_m5m6[isl.name]['RST'][0][0], 0]), gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(rrstout0, rg_m4m5, 'RSTOUT', laygen.layers['pin'][5], size=6, direction='bottom', netname='RST') # clk input laygen.create_boundary_pin_form_rect(rrst0, rg_m5m6, 'RST', laygen.layers['pin'][5], size=6, direction='top') # sarclk signal route # ckgen to fsm rh0, rv0, rh1 = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['CLKO'][0], pdict_m4m5[ifsm.name]['CLK'][0], pdict_m4m5[isl.name]['RETO<1>'][1][0] - 1, rg_m4m5) # datapath # ckdly route # sb rh0, rh0 = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickd.name]['SB'][0], pdict_m4m5[isl.name]['SB<4>'][0], rg_m4m5) # done [rh0, rv0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['DONE'][0], pdict_m5m6[ickd.name]['I'][0], pdict_m5m6[ickd.name]['I'][0][0], rg_m4m5) # up [rh0, rv0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['UP'][0], pdict_m5m6[ickd.name]['O'][0], pdict_m5m6[ickg.name]['UP'][0][0], rg_m4m5) # ckgen to sl route # saopb/saomb [rh0, rsaopb0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['SAOPB'][0], pdict_m5m6[isl.name]['SAOPB'][0], pdict_m5m6[ickg.name]['SAOPB'][0][0] + 1, rg_m4m5) [rh0, rsaomb0, rh1 ] = laygen.route_hvh(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m5m6[ickg.name]['SAOMB'][0], pdict_m5m6[isl.name]['SAOMB'][0], pdict_m5m6[ickg.name]['SAOMB'][0][0] + 2, rg_m4m5) # fsm to sl route # sb for i in range(num_bits): [rv0, rh0, rv1 ] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[ifsm.name]['SB<' + str(i) + '>'][0], pdict_m5m6[isl.name]['SB<' + str(i) + '>'][0], xysl[1] - i - 1, rg_m5m6) # zp/zm/zmid for i in range(num_bits): rzp0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m4m5[isl.name]['ZP<' + str(i) + '>'][0], xy1=pdict_m4m5[isl.name]['ZP<' + str(i) + '>'][0] + np.array([0, 4]), gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(rzp0, rg_m5m6, 'ZP<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='top') rzm0 = laygen.route(None, laygen.layers['metal'][5], xy0=pdict_m4m5[isl.name]['ZM<' + str(i) + '>'][0], xy1=pdict_m4m5[isl.name]['ZM<' + str(i) + '>'][0] + np.array([0, 4]), gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(rzm0, rg_m5m6, 'ZM<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='top') rzmid0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5[isl.name]['ZMID<' + str(i) + '>'][0], xy1=pdict_m4m5[isl.name]['ZMID<' + str(i) + '>'][0] + np.array([0, 4]), gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(rzmid0, rg_m5m6, 'ZMID<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='top') # ckdsel for i in range(2): rh0, rclkdsel0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickd.name]['SEL0<' + str(i) + '>'][0], np.array([pdict_m4m5[isl.name]['RETO<7>'][1][0] + 1 + i, 0]), rg_m4m5) laygen.create_boundary_pin_form_rect(rclkdsel0, rg_m4m5, 'CKDSEL0<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='bottom') rh0, rclkdsel0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickd.name]['SEL1<' + str(i) + '>'][0], np.array([pdict_m4m5[isl.name]['RETO<7>'][1][0] + 1 + i + 2, 0]), rg_m4m5) laygen.create_boundary_pin_form_rect(rclkdsel0, rg_m4m5, 'CKDSEL1<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='bottom') # SAOPB/SAOMB laygen.create_boundary_pin_form_rect(rsaopb0, rg_m4m5, 'SAOPB', laygen.layers['pin'][5], size=6, direction='top') laygen.create_boundary_pin_form_rect(rsaomb0, rg_m4m5, 'SAOMB', laygen.layers['pin'][5], size=6, direction='top') # extclk, extsel_clk rh0, rextclk0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['EXTCLK'][0], np.array([pdict_m4m5[ickg.name]['EXTCLK'][0][0] - 2 + 16, 0]), rg_m4m5) laygen.create_boundary_pin_form_rect(rextclk0, rg_m4m5, 'EXTCLK', laygen.layers['pin'][5], size=6, direction='bottom') rh0, rextsel_clk0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['EXTSEL_CLK'][0], np.array([pdict_m4m5[ickg.name]['EXTSEL_CLK'][0][0] - 4 + 16, 0]), rg_m4m5) laygen.create_boundary_pin_form_rect(rextsel_clk0, rg_m4m5, 'EXTSEL_CLK', laygen.layers['pin'][5], size=6, direction='bottom') # fsm to ret (data) for i in range(num_bits): [rv0, rh0, rv1 ] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], pdict_m5m6[isl.name]['RETO<' + str(i) + '>'][0], pdict_m5m6[iret.name]['IN<' + str(i) + '>'][0], xyfsm[1] - i - 1, rg_m5m6) # adcout for i in range(num_bits): radco0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5[iret.name]['OUT<' + str(i) + '>'][0], xy1=np.array( [pdict_m4m5[iret.name]['OUT<' + str(i) + '>'][0][0], 0]), gridname0=rg_m5m6) laygen.create_boundary_pin_form_rect(radco0, rg_m4m5, 'ADCOUT<' + str(i) + '>', laygen.layers['pin'][5], size=6, direction='bottom') # probe outputs laygen.pin(name='CLKPRB', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['CLKPRB'], gridname=rg_m4m5) laygen.pin(name='COMPOUT', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['COMPOUT'], gridname=rg_m4m5) laygen.pin(name='UP', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['UP'], gridname=rg_m4m5) laygen.pin(name='DONE', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['DONE'], gridname=rg_m4m5) laygen.pin(name='SARCLK', layer=laygen.layers['pin'][4], xy=pdict_m4m5[ickg.name]['CLKO'], gridname=rg_m4m5) rh0, rsclkb0 = laygen.route_hv( laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5[ickg.name]['CLKOB'][0], np.array([pdict_m4m5[ickg.name]['CLKOB'][1][0] + 12, y_top]), rg_m4m5) laygen.create_boundary_pin_form_rect(rsclkb0, rg_m4m5, 'SARCLKB', laygen.layers['pin'][5], size=6, direction='top') for i in range(num_bits): laygen.pin(name='SB<' + str(i) + '>', layer=laygen.layers['pin'][5], xy=pdict_m5m6[isl.name]['SB<' + str(i) + '>'], gridname=rg_m5m6) # vdd/vss # m3 rvddl_m3 = [] rvssl_m3 = [] rvddr_m3 = [] rvssr_m3 = [] xret_center = int( laygen.get_template_size( name=sarret_name, gridname=rg_m3m4_thick, libname=workinglib)[0] / 2) for p in pdict_m3m4[iret.name]: if p.startswith('VDD'): r0 = laygen.route(None, laygen.layers['metal'][3], xy0=pdict_m3m4[iret.name][p][0], xy1=pdict_m3m4[isp[-1].name][p][0], gridname0=rg_m3m4) if pdict_m3m4[iret.name][p][0][0] < xret_center: rvddl_m3.append(r0) else: rvddr_m3.append(r0) for p in pdict_m3m4[iret.name]: if p.startswith('VSS'): r0 = laygen.route(None, laygen.layers['metal'][3], xy0=pdict_m3m4[iret.name][p][0], xy1=pdict_m3m4[isp[-1].name][p][0], gridname0=rg_m3m4) if pdict_m3m4[iret.name][p][0][0] < xret_center: rvssl_m3.append(r0) else: rvssr_m3.append(r0) #m4 input_rails_rect = [rvddl_m3, rvssl_m3] rvddl_m4, rvssl_m4 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, offset_start_index=2, offset_end_index=-8) x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m3m4_thick, libname=utemplib)[0] input_rails_rect = [rvddr_m3, rvssr_m3] rvddr_m4, rvssr_m4 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=x1, offset_start_index=2, offset_end_index=-8) #additional m4 routes inst_exclude = [ isp[0], isp[1], iret, ifsm, isl, ickd, ickg, isp[-1], isp[-2] ] x0 = laygen.get_inst_xy(name=bnd_left[0].name, gridname=rg_m3m4_thick)[0] y0 = laygen.get_inst_xy(name=bnd_left[0].name, gridname=rg_m3m4_thick)[1] x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m3m4_thick, libname=utemplib)[0] y1 = laygen.get_inst_xy(name=bnd_left[-1].name, gridname=rg_m3m4_thick)[1] for i in range(y1 - y0): #check if y is not in the exclude area trig = 1 for iex in inst_exclude: if iex.transform == 'MX': yex0 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1]-1\ -laygen.get_template_size(name=iex.cellname, gridname=rg_m3m4_thick, libname=workinglib)[1] yex1 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1] + 1 else: yex0 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1] - 1 yex1 = laygen.get_inst_xy(name=iex.name, gridname=rg_m3m4_thick)[1]+1\ +laygen.get_template_size(name=iex.cellname, gridname=rg_m3m4_thick, libname=workinglib)[1] if y0 + i > yex0 and y0 + i < yex1: #exclude trig = 0 if trig == 1: r0 = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x0, y0 + i]), xy1=np.array([x1, y0 + i]), gridname0=rg_m3m4_thick) #m5 y1 = laygen.get_inst_xy(name=bnd_top[0].name, gridname=rg_m4m5_thick)[1]\ +laygen.get_template_size(name=bnd_top[0].cellname, gridname=rg_m4m5_thick)[1] input_rails_rect = [rvddl_m4, rvssl_m4] rvddl_m5, rvssl_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_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=0, overwrite_end_coord=y1, offset_start_index=1, offset_end_index=0) input_rails_rect = [rvddr_m4, rvssr_m4] rvddr_m5, rvssr_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_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=0, overwrite_end_coord=y1, offset_start_index=0, offset_end_index=0) #m6 input_rails_rect = [rvddl_m5, rvssl_m5] rvddl_m6, rvssl_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, offset_start_index=1, offset_end_index=-1) x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m5m6_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m5m6_thick, libname=utemplib)[0] input_rails_rect = [rvddr_m5, rvssr_m5] rvddr_m6, rvssr_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=x1, offset_start_index=1, offset_end_index=-1) #addtional m6 routes rvdd_m6 = [] rvss_m6 = [] inst_reference = [isp[0], isp[1], iret, ifsm, isl] #num_route=[10,10] num_route = [] for i, inst in enumerate(inst_reference): num_route.append( laygen.get_template_size(name=inst.cellname, gridname=rg_m5m6_thick, libname=workinglib)[1] - 2) x0 = laygen.get_inst_xy(name=bnd_left[0].name, gridname=rg_m5m6_thick)[0] x1 = laygen.get_inst_xy(name=bnd_right[0].name, gridname=rg_m5m6_thick)[0]\ +laygen.get_template_size(name=bnd_right[0].cellname, gridname=rg_m5m6_thick, libname=utemplib)[0] n_vdd_m6 = 0 #number for m6 wires n_vss_m6 = 0 #number for m6 wires for i, inst in enumerate(inst_reference): for j in range(num_route[i]): y0 = laygen.get_inst_xy(name=inst.name, gridname=rg_m5m6_thick)[1] + 1 r0 = laygen.route(None, laygen.layers['metal'][6], xy0=np.array([x0, y0 + j]), xy1=np.array([x1, y0 + j]), gridname0=rg_m5m6_thick) if j % 2 == 0: rvdd_m6.append(r0) xy0 = laygen.get_rect_xy(name=r0.name, gridname=rg_m5m6_thick) laygen.pin(name='VDD_M6' + str(n_vdd_m6), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDD') n_vdd_m6 += 1 else: rvss_m6.append(r0) xy0 = laygen.get_rect_xy(name=r0.name, gridname=rg_m5m6_thick) laygen.pin(name='VSS_M6' + str(n_vss_m6), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS') n_vss_m6 += 1
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_sarafe_nsw(laygen, objectname_pfix, workinglib, placement_grid, routing_grid_m2m3_thick, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6, routing_grid_m5m6_thick, routing_grid_m5m6_basic_thick, routing_grid_m6m7, num_bits=8, num_bits_vertical=6, num_cdrv_output_routes=2, m_sa=8, origin=np.array([0, 0])): """generate sar analog frontend """ pg = placement_grid rg_m3m4_thick = routing_grid_m3m4_thick rg_m5m6 = routing_grid_m5m6 rg_m6m7 = routing_grid_m6m7 tap_name = 'tap' cdrv_name = 'capdrv_nsw_array' #cdac_name='capdac_'+str(num_bits)+'b' cdac_name = 'capdac' sa_name = 'doubleSA_pmos' # placement xy0 = origin + (laygen.get_template_size( cdrv_name, gridname=pg, libname=workinglib) * np.array([1, 0])) icdrvl = laygen.place(name="I" + objectname_pfix + 'CDRVL0', templatename=cdrv_name, gridname=pg, xy=xy0, template_libname=workinglib, transform='MY') icdrvr = laygen.place(name="I" + objectname_pfix + 'CDRVR0', templatename=cdrv_name, gridname=pg, xy=xy0, template_libname=workinglib) xy0 = origin + laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([0, 1]) \ + laygen.get_template_size(sa_name, gridname=pg, libname=workinglib) * np.array([0, 1]) isa = laygen.place(name="I" + objectname_pfix + 'SA0', templatename=sa_name, gridname=pg, xy=xy0, template_libname=workinglib, transform='MX') xy0 = origin + laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([0, 1]) \ + laygen.get_template_size(sa_name, gridname=pg, libname=workinglib) * np.array([0, 1]) \ + laygen.get_template_size(cdac_name, gridname=pg, libname=workinglib)*np.array([1, 0]) icdacl = laygen.place(name="I" + objectname_pfix + 'CDACL0', templatename=cdac_name, gridname=pg, xy=xy0, template_libname=workinglib, transform='MY') xy0 = origin + laygen.get_template_size(cdrv_name, gridname=pg, libname=workinglib)*np.array([2, 1]) \ + laygen.get_template_size(sa_name, gridname=pg, libname=workinglib) * np.array([0, 1]) \ - laygen.get_template_size(cdac_name, gridname=pg, libname=workinglib)*np.array([1, 0]) icdacr = laygen.place(name="I" + objectname_pfix + 'CDACR0', templatename=cdac_name, gridname=pg, xy=xy0, template_libname=workinglib) # pin informations pdict_m3m4_thick = laygen.get_inst_pin_xy(None, None, rg_m3m4_thick) # internal pins icdrvl_vo_xy = [] icdacl_i_xy = [] icdacl_i2_xy = [] icdrvr_vo_xy = [] icdacr_i_xy = [] icdacr_i2_xy = [] icdrvl_vo_c0_xy = laygen.get_inst_pin_xy(icdrvl.name, 'VO_C0', rg_m5m6) icdacl_i_c0_xy = laygen.get_inst_pin_xy(icdacl.name, 'I_C0', rg_m5m6) icdrvr_vo_c0_xy = laygen.get_inst_pin_xy(icdrvr.name, 'VO_C0', rg_m5m6) icdacr_i_c0_xy = laygen.get_inst_pin_xy(icdacr.name, 'I_C0', rg_m5m6) for i in range(num_bits): icdacl_i_xy.append( laygen.get_inst_pin_xy(icdacl.name, 'I<' + str(i) + '>', rg_m4m5)) icdacr_i_xy.append( laygen.get_inst_pin_xy(icdacr.name, 'I<' + str(i) + '>', rg_m4m5)) if i >= num_bits_vertical: icdacl_i2_xy.append( laygen.get_inst_pin_xy(icdacl.name, 'I2<' + str(i) + '>', rg_m4m5)) icdacr_i2_xy.append( laygen.get_inst_pin_xy(icdacr.name, 'I2<' + str(i) + '>', rg_m4m5)) for j in range(num_cdrv_output_routes): for i in range(num_bits): icdrvl_vo_xy.append( laygen.get_inst_pin_xy(icdrvl.name, 'VO' + str(j) + '<' + str(i) + '>', rg_m5m6)) icdrvr_vo_xy.append( laygen.get_inst_pin_xy(icdrvr.name, 'VO' + str(j) + '<' + str(i) + '>', rg_m5m6)) #route #capdrv to capdac #y0 = origin[1] + laygen.get_template_size(cdrv_name, gridname=rg_m5m6, libname=workinglib)[1]-2 #refer to capdrv y0 = origin[1] + laygen.get_template_size(cdrv_name, gridname=rg_m4m5, libname=workinglib)[1] \ + laygen.get_template_size(sa_name, gridname=rg_m4m5, libname=workinglib)[1]-4 #refer to sa [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvl_vo_c0_xy[0], icdacl_i_c0_xy[0], y0 + 1, rg_m5m6, layerv1=laygen.layers['metal'][5], gridname1=rg_m5m6) laygen.boundary_pin_from_rect(rv0, rg_m4m5, "VOL_C0", laygen.layers['pin'][5], size=4, direction='bottom', netname='VREF<1>') [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvr_vo_c0_xy[0], icdacr_i_c0_xy[0], y0 + 1, rg_m5m6, layerv1=laygen.layers['metal'][5], gridname1=rg_m5m6) laygen.boundary_pin_from_rect(rv0, rg_m4m5, "VOR_C0", laygen.layers['pin'][5], size=4, direction='bottom', netname='VREF<1>') for j in range(num_cdrv_output_routes): for i in range(num_bits): if i in range(num_bits_vertical) and i % 2 == (num_bits_vertical + 1) % 2: #if not i%2==num_bits_vertical%2: [rv0l, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][4], icdrvl_vo_xy[i + j * num_bits][0], icdacl_i_xy[i][0], y0 - i - 1, rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4) [rv0r, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][4], icdrvr_vo_xy[i + j * num_bits][0], icdacr_i_xy[i][0], y0 - i - 1, rg_m4m5, layerv1=laygen.layers['metal'][3], gridname1=rg_m3m4) else: [rv0l, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvl_vo_xy[i + j * num_bits][0], icdacl_i_xy[i][0], y0 - i - 1, rg_m5m6, layerv1=laygen.layers['metal'][5], gridname1=rg_m5m6) [rv0r, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][6], icdrvr_vo_xy[i + j * num_bits][0], icdacr_i_xy[i][0], y0 - i - 1, rg_m5m6, layerv1=laygen.layers['metal'][5], gridname1=rg_m5m6) laygen.boundary_pin_from_rect(rv0l, rg_m4m5, "VOL<" + str(i) + ">", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(rv0r, rg_m4m5, "VOR<" + str(i) + ">", laygen.layers['pin'][5], size=4, direction='bottom') #more routes for horizontal dacs if i >= num_bits_vertical: [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][4], icdrvl_vo_xy[i + j * num_bits][0], icdacl_i_xy[i][0], y0 + 2 + i - num_bits_vertical, rg_m4m5, layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5) [rv0, rh0, rv1] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][4], icdrvr_vo_xy[i + j * num_bits][0], icdacr_i_xy[i][0], y0 + 2 + i - num_bits_vertical, rg_m4m5, layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5) [rv0, rh0, rv1 ] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][4], icdrvl_vo_xy[i + j * num_bits][0], icdacl_i2_xy[i - num_bits_vertical][0], y0 + 2 + i - num_bits_vertical, rg_m4m5, layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5) [rv0, rh0, rv1 ] = laygen.route_vhv(laygen.layers['metal'][5], laygen.layers['metal'][4], icdrvr_vo_xy[i + j * num_bits][0], icdacr_i2_xy[i - num_bits_vertical][0], y0 + 2 + i - num_bits_vertical, rg_m4m5, layerv1=laygen.layers['metal'][5], gridname1=rg_m4m5) #vref rvref0 = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='VREF<0>', gridname0=rg_m4m5, refinstname1=icdrvr.name, refpinname1='VREF<0>') rvref1 = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='VREF<1>', gridname0=rg_m4m5, refinstname1=icdrvr.name, refpinname1='VREF<1>') rvref2 = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='VREF<2>', gridname0=rg_m4m5, refinstname1=icdrvr.name, refpinname1='VREF<2>') #input pins #y0 = laygen.get_inst_pin_xy(icdrvl.name, 'EN0<0>', rg_m4m5, index=np.array([0, 0]), sort=True)[0][1] y0 = 0 rclkb = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='CLKB', gridname0=rg_m4m5, direction='y') routp = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='OUTP', gridname0=rg_m4m5, direction='y') routm = laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=isa.name, refpinname0='OUTM', gridname0=rg_m4m5, direction='y') #rosp=laygen.route(None, laygen.layers['metal'][3], xy0=np.array([0, 0]), xy1=np.array([0, 0]), # refinstname0=isa.name, refpinname0='OSP', gridname0=rg_m2m3, direction='y') #rosm=laygen.route(None, laygen.layers['metal'][3], xy0=np.array([0, 0]), xy1=np.array([0, 0]), # refinstname0=isa.name, refpinname0='OSM', gridname0=rg_m2m3, direction='y') pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4) yos=laygen.get_inst_xy(isa.name, rg_m3m4)[1] \ - laygen.get_template_size(name=isa.cellname, gridname=rg_m3m4, libname=workinglib)[1] [rv0, rh0, rosp] = laygen.route_vhv( laygen.layers['metal'][3], laygen.layers['metal'][4], pdict_m3m4[isa.name]['OSP'][0], np.array([pdict_m3m4[isa.name]['OSP'][0][0] + m_sa, 0]), yos, rg_m3m4) [rv0, rh0, rosm] = laygen.route_vhv( laygen.layers['metal'][3], laygen.layers['metal'][4], pdict_m3m4[isa.name]['OSM'][0], np.array([pdict_m3m4[isa.name]['OSM'][0][0] - m_sa, 0]), yos, rg_m3m4) renl0 = [] renl1 = [] renl2 = [] renr0 = [] renr1 = [] renr2 = [] for i in range(num_bits): renl0.append( laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='EN' + str(i) + '<0>', gridname0=rg_m5m6, direction='y')) renl1.append( laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='EN' + str(i) + '<1>', gridname0=rg_m5m6, direction='y')) renl2.append( laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvl.name, refpinname0='EN' + str(i) + '<2>', gridname0=rg_m5m6, direction='y')) renr0.append( laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvr.name, refpinname0='EN' + str(i) + '<0>', gridname0=rg_m5m6, direction='y')) renr1.append( laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvr.name, refpinname0='EN' + str(i) + '<1>', gridname0=rg_m5m6, direction='y')) renr2.append( laygen.route(None, laygen.layers['metal'][5], xy0=np.array([0, 0]), xy1=np.array([0, 0]), refinstname0=icdrvr.name, refpinname0='EN' + str(i) + '<2>', gridname0=rg_m5m6, direction='y')) #inp/inm pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4) outcnt = 0 for pn in pdict_m3m4[icdacl.name]: if pn.startswith('O'): #out pin outcnt += 1 x0 = laygen.get_inst_xy(icdacl.name, rg_m3m4)[0] - 8 x1 = laygen.get_inst_xy(icdacr.name, rg_m3m4)[0] + 8 nrin_sa = 4 # number of M6 horizontal route stacks for cdac to sa nrin = 2**num_bits_vertical - 2 * nrin_sa # number of M6 horizontal route stacks if nrin < 1: nrin = 2**num_bits_vertical - nrin_sa rinp = [] rinm = [] for i in range(nrin): xy0 = laygen.get_inst_pin_xy(icdacl.name, "O" + str(outcnt - 1 - i), rg_m3m4, index=np.array([0, 0]), sort=True)[0] r = laygen.route(None, laygen.layers['metal'][4], xy0=xy0, xy1=np.array([x0, xy0[1]]), gridname0=rg_m3m4) rinp.append(r) ''' #additional routes for dummy for density rules; may not process portable for j in range(3): laygen.route(None, laygen.layers['metal'][6], xy0=xy0+np.array([0, 2*j+2]), xy1=np.array([x0, xy0[1]+2*j+2]), gridname0=rg_m5m6) ''' xy0 = laygen.get_inst_pin_xy(icdacr.name, "O" + str(outcnt - 1 - i), rg_m3m4, index=np.array([0, 0]), sort=True)[1] r = laygen.route(None, laygen.layers['metal'][4], xy0=xy0, xy1=np.array([x1, xy0[1]]), gridname0=rg_m3m4) rinm.append(r) ''' #additional routes for dummy for density rules; may not process portable for j in range(3): laygen.route(None, laygen.layers['metal'][6], xy0=xy0+np.array([0, 2*j+2]), xy1=np.array([x1, xy0[1]+2*j+2]), gridname0=rg_m5m6) ''' for i in range(nrin_sa): xy0 = laygen.get_inst_pin_xy(icdacl.name, "O" + str(i), rg_m3m4, index=np.array([0, 0]), sort=True)[0] laygen.route(None, laygen.layers['metal'][4], xy0=xy0, xy1=np.array([x0, xy0[1]]), gridname0=rg_m4m5) for j in range(4): laygen.via(None, [x0 - 2 * j, xy0[1]], rg_m4m5) xy0 = laygen.get_inst_pin_xy(icdacr.name, "O" + str(i), rg_m3m4, index=np.array([0, 0]), sort=True)[1] laygen.route(None, laygen.layers['metal'][4], xy0=xy0, xy1=np.array([x1, xy0[1]]), gridname0=rg_m4m5) for j in range(4): laygen.via(None, [x1 + 2 * j, xy0[1]], rg_m4m5) xy0 = laygen.get_inst_pin_xy(isa.name, "INP", rg_m3m4, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_xy(icdacl.name, "O" + str(nrin_sa - 1), rg_m4m5, index=np.array([0, 0]), sort=True)[0] for j in range(4): laygen.route(None, laygen.layers['metal'][5], xy0=np.array([x0 - 2 * j, xy0[1]]), xy1=np.array([x0 - 2 * j, xy1[1]]), gridname0=rg_m5m6) xy0 = laygen.get_inst_pin_xy(isa.name, "INM", rg_m4m5, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_xy(icdacr.name, "O" + str(nrin_sa - 1), rg_m5m6, index=np.array([0, 0]), sort=True)[0] for j in range(4): laygen.route(None, laygen.layers['metal'][5], xy0=np.array([x1 + 2 * j, xy0[1]]), xy1=np.array([x1 + 2 * j, xy1[1]]), gridname0=rg_m5m6) #inp/inm - sa to capdac xy0 = laygen.get_inst_pin_xy(isa.name, "INP", rg_m4m5, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_xy(isa.name, "INM", rg_m4m5, index=np.array([0, 0]), sort=True)[0] rsainp = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x0 - 8, xy0[1]]), xy1=xy0, gridname0=rg_m4m5) rsainm = laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x1 + 8, xy1[1]]), xy1=xy1, gridname0=rg_m4m5) for j in range(4): laygen.via(None, [x0 - 2 * j, xy0[1]], rg_m4m5) laygen.via(None, [x1 + 2 * j, xy1[1]], rg_m4m5) x0 = laygen.get_inst_xy(icdacl.name, rg_m3m4)[0] - 1 x1 = laygen.get_inst_xy(icdacr.name, rg_m3m4)[0] + 1 xy0 = laygen.get_inst_pin_xy(isa.name, "INP", rg_m3m4, index=np.array([0, 0]), sort=True)[0] xy1 = laygen.get_inst_pin_xy(isa.name, "INM", rg_m3m4, index=np.array([0, 0]), sort=True)[0] laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x0, xy0[1]]), xy1=xy0, gridname0=rg_m3m4, via1=[[0, 0]]) laygen.route(None, laygen.layers['metal'][4], xy0=np.array([x1, xy1[1]]), xy1=xy1, gridname0=rg_m3m4, via1=[[0, 0]]) #vdd/vss - route #cdrv_left_m4 rvdd_cdrvl_m3 = [] rvss_cdrvl_m3 = [] for pn, p in pdict_m3m4_thick[icdrvl.name].items(): if pn.startswith('VSSR'): rvss_cdrvl_m3.append(p) input_rails_xy = [rvss_cdrvl_m3] rvss_cdrvl_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_CDRVL_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rvss_cdrvl_m4 = rvss_cdrvl_m4[0] #cdrv_right_m4 x1 = laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=icdrvr.cellname, gridname=rg_m3m4_thick, libname=workinglib)[0] rvdd_cdrvr_m3 = [] rvss_cdrvr_m3 = [] for pn, p in pdict_m3m4_thick[icdrvr.name].items(): if pn.startswith('VSSR'): rvss_cdrvr_m3.append(p) input_rails_xy = [rvss_cdrvr_m3] rvss_cdrvr_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_CDRVR_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=x1, offset_start_index=0, offset_end_index=0) rvss_cdrvr_m4 = rvss_cdrvr_m4[0] #sa_left_m4_m5 rvdd_sal_m3 = [] rvss_sal_m3 = [] for pn, p in pdict_m3m4_thick[isa.name].items(): if pn.startswith('VDDL'): rvdd_sal_m3.append(p) if pn.startswith('VSSL'): rvss_sal_m3.append(p) input_rails_xy = [rvdd_sal_m3, rvss_sal_m3] rvdd_sal_m4, rvss_sal_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_SAL_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=0, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-4) #input_rails_rect = [rvdd_sal_m4+rvdd_cdrvl_m4, rvss_sal_m4+rvss_cdrvl_m4] input_rails_rect = [rvdd_sal_m4, rvss_sal_m4 + rvss_cdrvl_m4] rvdd_sal_m5, rvss_sal_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAL_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=0, overwrite_end_coord=None, offset_start_index=1, offset_end_index=-6) #sa_right_m4_m5 x1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m3m4_thick)[0]\ +laygen.get_template_size(name=isa.cellname, gridname=rg_m3m4_thick, libname=workinglib)[0] rvdd_sar_m3 = [] rvss_sar_m3 = [] for pn, p in pdict_m3m4_thick[isa.name].items(): if pn.startswith('VDDR'): rvdd_sar_m3.append(p) if pn.startswith('VSSR'): rvss_sar_m3.append(p) input_rails_xy = [rvdd_sar_m3, rvss_sar_m3] rvdd_sar_m4, rvss_sar_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_SAR_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=x1, offset_start_index=0, offset_end_index=-4) #input_rails_rect = [rvdd_sar_m4+rvdd_cdrvr_m4, rvss_sar_m4+rvss_cdrvr_m4] input_rails_rect = [rvdd_sar_m4, rvss_sar_m4 + rvss_cdrvr_m4] rvdd_sar_m5, rvss_sar_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_SAR_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=0, overwrite_end_coord=None, offset_start_index=8, offset_end_index=0) #sa_m6 num_vref_routes_m6 = 4 x1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m5m6_thick)[0]\ +laygen.get_template_size(name=isa.cellname, gridname=rg_m5m6_thick, libname=workinglib)[0] x1_phy = laygen.get_inst_xy(name=isa.name)[0]\ +laygen.get_template_size(name=isa.cellname, libname=workinglib)[0] y1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m5m6_thick)[1] input_rails_rect = [rvdd_sal_m5 + rvdd_sar_m5, rvss_sal_m5 + rvss_sar_m5] #sa_m6_bottom_shield rvdd_sa_m6, rvss_sa_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_0_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=x1, overwrite_start_index=2, overwrite_end_index=4) #trimming for r in rvdd_sa_m6: r.xy1[0] = x1_phy for r in rvss_sa_m6: r.xy1[0] = x1_phy #sa_m6_mid and top_shield for i in range(3): rvss_sa_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_' + str(i + 1) + '_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VSS'], direction='x', input_rails_rect=[rvss_sal_m5 + rvss_sar_m5], generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=x1, overwrite_start_index=4 + (1 + num_vref_routes_m6) * (i + 1) - 1, overwrite_num_routes=0 ) #overwrite_end_index=4+(1+num_vref_routes_m6)*(i+1)) #trimming for r in rvss_sa_m6[0]: r.xy1[0] = x1_phy #sa_m6_top_main_route rvdd_sa_m6, rvss_sa_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=x1, offset_start_index=4 + (1 + num_vref_routes_m6) * 3, offset_end_index=0) #trimming and pinning for r in rvdd_sa_m6: r.xy1[0] = x1_phy p = laygen.pin_from_rect(name='VDD_M6_' + r.name, layer=laygen.layers['pin'][6], rect=r, gridname=rg_m5m6_thick, netname='VDD') p.xy1[0] = x1_phy for r in rvss_sa_m6: r.xy1[0] = x1_phy p = laygen.pin_from_rect(name='VSS_M6_' + r.name, layer=laygen.layers['pin'][6], rect=r, gridname=rg_m5m6_thick, netname='VSS') p.xy1[0] = x1_phy #pins #laygen.pin(name='VREF<0>', layer=laygen.layers['pin'][4], xy=laygen.get_rect_xy(rvref0.name, rg_m4m5), gridname=rg_m4m5) #laygen.pin(name='VREF<1>', layer=laygen.layers['pin'][4], xy=laygen.get_rect_xy(rvref1.name, rg_m4m5), gridname=rg_m4m5) #laygen.pin(name='VREF<2>', layer=laygen.layers['pin'][4], xy=laygen.get_rect_xy(rvref2.name, rg_m4m5), gridname=rg_m4m5) ''' t = laygen.templates.get_template(icdrvl.cellname, libname=workinglib) vref0vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5<0>', rg_m4m5, libname=workinglib) vref1vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5<1>', rg_m4m5, libname=workinglib) vref2vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5<2>', rg_m4m5, libname=workinglib) vref0vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5<0>', rg_m4m5, libname=workinglib) vref1vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5<1>', rg_m4m5, libname=workinglib) vref2vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5<2>', rg_m4m5, libname=workinglib) laygen.pin(name='VREF_M5L<0>', layer=laygen.layers['pin'][5], xy=vref0vl_pin_xy, gridname=rg_m4m5, netname='VREF<0>') laygen.pin(name='VREF_M5L<1>', layer=laygen.layers['pin'][5], xy=vref1vl_pin_xy, gridname=rg_m4m5, netname='VREF<1>') laygen.pin(name='VREF_M5L<2>', layer=laygen.layers['pin'][5], xy=vref2vl_pin_xy, gridname=rg_m4m5, netname='VREF<2>') laygen.pin(name='VREF_M5R<0>', layer=laygen.layers['pin'][5], xy=vref0vr_pin_xy, gridname=rg_m4m5, netname='VREF<0>') laygen.pin(name='VREF_M5R<1>', layer=laygen.layers['pin'][5], xy=vref1vr_pin_xy, gridname=rg_m4m5, netname='VREF<1>') laygen.pin(name='VREF_M5R<2>', layer=laygen.layers['pin'][5], xy=vref2vr_pin_xy, gridname=rg_m4m5, netname='VREF<2>') vref0vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5_2<0>', rg_m4m5, libname=workinglib) vref1vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5_2<1>', rg_m4m5, libname=workinglib) vref2vl_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvl.name, gridname=rg_m4m5), (2,1))\ + np.array([-1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5_2<2>', rg_m4m5, libname=workinglib) vref0vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5_2<0>', rg_m4m5, libname=workinglib) vref1vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5_2<1>', rg_m4m5, libname=workinglib) vref2vr_pin_xy=np.tile(laygen.get_inst_xy(name=icdrvr.name, gridname=rg_m4m5), (2,1))\ + np.array([1, 1]) * laygen.get_template_pin_xy(t.name, 'VREF_M5_2<2>', rg_m4m5, libname=workinglib) laygen.pin(name='VREF_M5L_2<0>', layer=laygen.layers['pin'][5], xy=vref0vl_pin_xy, gridname=rg_m4m5, netname='VREF<0>') laygen.pin(name='VREF_M5L_2<1>', layer=laygen.layers['pin'][5], xy=vref1vl_pin_xy, gridname=rg_m4m5, netname='VREF<1>') laygen.pin(name='VREF_M5L_2<2>', layer=laygen.layers['pin'][5], xy=vref2vl_pin_xy, gridname=rg_m4m5, netname='VREF<2>') laygen.pin(name='VREF_M5R_2<0>', layer=laygen.layers['pin'][5], xy=vref0vr_pin_xy, gridname=rg_m4m5, netname='VREF<0>') laygen.pin(name='VREF_M5R_2<1>', layer=laygen.layers['pin'][5], xy=vref1vr_pin_xy, gridname=rg_m4m5, netname='VREF<1>') laygen.pin(name='VREF_M5R_2<2>', layer=laygen.layers['pin'][5], xy=vref2vr_pin_xy, gridname=rg_m4m5, netname='VREF<2>') ''' pdict_vref = laygen.get_inst_pin_xy(None, None, rg_m5m6_basic_thick) x1 = laygen.get_inst_xy(name=isa.name, gridname=rg_m5m6_basic_thick)[0]\ +laygen.get_template_size(name=isa.cellname, gridname=rg_m5m6_basic_thick, libname=workinglib)[0] for i in range(3): laygen.route( None, laygen.layers['metal'][5], gridname0=rg_m5m6_basic_thick, xy0=pdict_vref[icdrvl.name]['VREF_M5<' + str(i) + '>'][0], xy1=pdict_vref[icdrvl.name]['VREF_M5<' + str(i) + '>'][0] + np.array([0, (num_vref_routes_m6 + 1) * 3 + 4])) laygen.route( None, laygen.layers['metal'][5], gridname0=rg_m5m6_basic_thick, xy0=pdict_vref[icdrvr.name]['VREF_M5<' + str(i) + '>'][0], xy1=pdict_vref[icdrvr.name]['VREF_M5<' + str(i) + '>'][0] + np.array([0, (num_vref_routes_m6 + 1) * 3 + 4])) laygen.route( None, laygen.layers['metal'][5], gridname0=rg_m5m6_basic_thick, xy0=pdict_vref[icdrvl.name]['VREF_M5_2<' + str(i) + '>'][0], xy1=pdict_vref[icdrvl.name]['VREF_M5_2<' + str(i) + '>'][0] + np.array([0, (num_vref_routes_m6 + 1) * 3 + 4])) laygen.route( None, laygen.layers['metal'][5], gridname0=rg_m5m6_basic_thick, xy0=pdict_vref[icdrvr.name]['VREF_M5_2<' + str(i) + '>'][0], xy1=pdict_vref[icdrvr.name]['VREF_M5_2<' + str(i) + '>'][0] + np.array([0, (num_vref_routes_m6 + 1) * 3 + 4])) input_rails_xy = [[ pdict_vref[icdrvl.name]['VREF_M5<' + str(i) + '>'], pdict_vref[icdrvl.name]['VREF_M5_2<' + str(i) + '>'], pdict_vref[icdrvr.name]['VREF_M5<' + str(i) + '>'], pdict_vref[icdrvr.name]['VREF_M5_2<' + str(i) + '>'] ]] laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M6_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_basic_thick, netnames=['VREF<' + str(i) + '>'], direction='x', input_rails_xy=input_rails_xy, generate_pin=True, overwrite_start_coord=0, overwrite_end_coord=x1, overwrite_start_index=4 + (num_vref_routes_m6 + 1) * i, overwrite_end_index=4 + (num_vref_routes_m6 + 1) * i + num_vref_routes_m6 - 1) laygen.boundary_pin_from_rect(rclkb, rg_m4m5, "CLKB", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(routp, rg_m4m5, "OUTP", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(routm, rg_m4m5, "OUTM", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(rosp, rg_m2m3, "OSP", laygen.layers['pin'][3], size=4, direction='bottom') laygen.boundary_pin_from_rect(rosm, rg_m2m3, "OSM", laygen.layers['pin'][3], size=4, direction='bottom') for i in range(num_bits): laygen.boundary_pin_from_rect(renl0[i], rg_m5m6, "ENL" + str(i) + "<0>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(renl1[i], rg_m5m6, "ENL" + str(i) + "<1>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(renl2[i], rg_m5m6, "ENL" + str(i) + "<2>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(renr0[i], rg_m5m6, "ENR" + str(i) + "<0>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(renr1[i], rg_m5m6, "ENR" + str(i) + "<1>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.boundary_pin_from_rect(renr2[i], rg_m5m6, "ENR" + str(i) + "<2>", laygen.layers['pin'][5], size=4, direction='bottom') laygen.pin_from_rect(name='SAINP', layer=laygen.layers['pin'][4], rect=rsainp, gridname=rg_m4m5, netname='INP') laygen.pin_from_rect(name='SAINM', layer=laygen.layers['pin'][4], rect=rsainm, gridname=rg_m4m5, netname='INM') for i, r in enumerate(rinp): laygen.boundary_pin_from_rect(r, rg_m4m5, "INP" + str(i), laygen.layers['pin'][4], size=8, direction='right', netname="INP") for i, r in enumerate(rinm): laygen.boundary_pin_from_rect(r, rg_m4m5, "INM" + str(i), laygen.layers['pin'][4], size=8, direction='left', netname="INM")
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_space_array(laygen, objectname_pfix, tisar_libname, space_libname, tisar_name, space_name, placement_grid, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, origin=np.array([0, 0])): """generate tisar space """ pg = placement_grid ttisar = laygen.templates.get_template(tisar_name, libname=tisar_libname) tspace = laygen.templates.get_template(space_name, libname=space_libname) sar_pins = ttisar.pins tbnd_bottom = laygen.templates.get_template('boundary_bottom') tbnd_bleft = laygen.templates.get_template('boundary_bottomleft') space_xy = np.array([tspace.size[0], ttisar.size[1]]) # laygen.add_rect(None, np.array([origin, origin+space_xy+2*tbnd_bleft.size[0]*np.array([1, 0])]), laygen.layers['prbnd']) # num_space_tot=int((ttisar.size[1]-2*tbnd_bottom.size[1])/tspace.size[1]) # tbnd_bleft_size=tbnd_bleft.size #VDD/VSS/VREF integration rvddclkd = [] rvddsamp = [] rvddsar = [] rvddsar_upper = [] rvref0 = [] rvref1 = [] rvref2 = [] rvssclkd = [] rvsssamp = [] rvsssar = [] rvsssar_upper = [] vddclkd_xy = [] vddsamp_xy = [] vddsar_xy = [] vddsar_upper_xy = [] vssclkd_xy = [] vsssamp_xy = [] vsssar_xy = [] vsssar_upper_xy = [] y_vddsar_max = 0 y_vddsar_lower_max = 0 y_vddsamp_min = 500000 y_vddsamp_max = 0 y_vddclkd_min = 500000 y_vref0 = sar_pins['VREF0<0>']['xy'][0][1] num_unit_row = 4 num_unit_col = 3 ispace_sar = [] for col in range(num_unit_col): ispace_sar.append([]) space_origin = origin + [ col * laygen.get_template_xy(space_name, pg, workinglib)[0], 0 ] ispace_sar[col].append( laygen.place(name="I" + objectname_pfix + 'SPSAR' + str(col), templatename=space_name, gridname=pg, xy=space_origin, template_libname=space_libname)) for i in range(1, num_unit_row): if i % 2 == 0: ispace_sar[col].append( laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(col) + str(i), templatename=space_name, gridname=pg, refinstname=ispace_sar[col][-1].name, direction='top', transform='R0', template_libname=space_libname)) else: ispace_sar[col].append( laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(col) + str(i), templatename=space_name, gridname=pg, refinstname=ispace_sar[col][-1].name, direction='top', transform='MX', template_libname=space_libname)) # # m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) # [bnd_bottom, bnd_top, bnd_left, bnd_right] \ # = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAR0', placement_grid=pg, # devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], # shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], # devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], # shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], # devname_left=devname_bnd_left, # transform_left=transform_bnd_left, # devname_right=devname_bnd_right, # transform_right=transform_bnd_right, # origin=origin) # #vddsamp cap # num_space_samp=num_space_tot-num_space_sar-1 # space_origin = origin + laygen.get_xy(obj=laygen.get_template(name = 'boundary_bottomleft'), gridname = pg) * np.array([1, (3 + 2 * num_space_sar)]) # ispace_samp = [laygen.place(name="I" + objectname_pfix + 'SPSAMP0', templatename=space_name, # gridname=pg, xy=space_origin, template_libname=space_libname)] # devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'] # devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'] # transform_bnd_left = ['R0', 'MX'] # transform_bnd_right = ['R0', 'MX'] # # for i in range(1, num_space_samp): # if i % 2 == 0: # ispace_samp.append(laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i), templatename=space_name, # gridname=pg, refinstname=ispace_samp[-1].name, direction='top', transform='R0', # template_libname=space_libname)) # devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] # devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] # transform_bnd_left += ['R0', 'MX'] # transform_bnd_right += ['R0', 'MX'] # else: # ispace_samp.append(laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i), templatename=space_name, # gridname=pg, refinstname=ispace_samp[-1].name, direction='top', transform='MX', # template_libname=space_libname)) # devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] # devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] # transform_bnd_left += ['R0', 'MX'] # transform_bnd_right += ['R0', 'MX'] # # m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) # [bnd_bottom, bnd_top, bnd_left, bnd_right] \ # = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAMP0', placement_grid=pg, # devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], # shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], # devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], # shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], # devname_left=devname_bnd_left, # transform_left=transform_bnd_left, # devname_right=devname_bnd_right, # transform_right=transform_bnd_right, # origin=space_origin-laygen.get_xy(obj=laygen.get_template(name = 'boundary_bottomleft'), gridname = pg)) #vdd/vss #m3 rvdd_sar_xy_m3 = [] rvss_sar_xy_m3 = [] space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins vddcnt = 0 vsscnt = 0 for col in range(num_unit_col): space_origin_phy = ispace_sar[col][0].bbox[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_unit_row])]) pxy[0][1] = y_vddsar_lower_max pxy[1][1] = ispace_sar[0][-1].bbox[1][1] laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvdd_sar_xy_m3.append( laygen.grids.get_absgrid_coord_region( gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vddcnt += 1 if pn.startswith('VSS'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_unit_row])]) pxy[0][1] = y_vddsar_lower_max pxy[1][1] = ispace_sar[0][-1].bbox[1][1] laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvss_sar_xy_m3.append( laygen.grids.get_absgrid_coord_region( gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vsscnt += 1 print(vddcnt, vsscnt) # rvdd_samp_xy_m3=[] # rvss_samp_xy_m3=[] # space_template = laygen.templates.get_template(space_name, workinglib) # space_pins=space_template.pins # space_origin_phy = ispace_samp[0].bbox[0] # vddcnt=0 # vsscnt=0 # for pn, p in space_pins.items(): # if pn.startswith('VDD'): # pxy=space_origin_phy+np.array([p['xy'][0], p['xy'][1]*np.array([1, num_space_samp])]) # laygen.add_rect(None, pxy, laygen.layers['metal'][3]) # rvdd_samp_xy_m3.append(laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) # vddcnt += 1 # if pn.startswith('VSS'): # pxy=space_origin_phy+np.array([p['xy'][0], p['xy'][1]*np.array([1, num_space_samp])]) # laygen.add_rect(None, pxy, laygen.layers['metal'][3]) # rvss_samp_xy_m3.append(laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) # vsscnt += 1 #m4 # input_rails_xy = [rvdd_samp_xy_m3, rvss_samp_xy_m3] # rvdd_samp_m4, rvss_samp_m4 = laygenhelper.generate_power_rails_from_rails_xy(laygen, routename_tag='_M4_SAMP_', layer=laygen.layers['metal'][4], # gridname=rg_m3m4_thick, netnames=['VDDSAMP', 'VSSSAMP'], direction='x', # input_rails_xy=input_rails_xy, generate_pin=False, # overwrite_start_coord=None, overwrite_end_coord=None, # offset_start_index=0, offset_end_index=0) end = laygen.get_xy(obj = ispace_sar[-1][0], gridname=rg_m3m4_thick)[0]\ +laygen.get_xy(obj = ispace_sar[-1][0].template, gridname=rg_m3m4_thick)[0] input_rails_xy = [rvdd_sar_xy_m3, rvss_sar_xy_m3] rvdd_sar_m4, rvss_sar_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_', 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=0, overwrite_end_coord=end, offset_start_index=0, offset_end_index=0) end = laygen.get_xy(obj=ispace_sar[-1][-1], gridname=rg_m4m5_thick)[1] if num_unit_row % 2 == 1: end = end + laygen.get_xy(obj=ispace_sar[-1][0].template, gridname=rg_m4m5_thick)[1] input_rails_rect = [rvdd_sar_m4, rvss_sar_m4] rvdd_sar_m5, rvss_sar_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_', 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=0, overwrite_end_coord=end, offset_start_index=0, offset_end_index=0) end = laygen.get_xy(obj = ispace_sar[-1][0], gridname=rg_m5m6_thick)[0]\ +laygen.get_xy(obj = ispace_sar[-1][0].template, gridname=rg_m5m6_thick)[0] input_rails_rect = [rvdd_sar_m5, rvss_sar_m5] rvdd_sar_m6, rvss_sar_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=end, offset_start_index=0, offset_end_index=0) end = laygen.get_xy(obj=ispace_sar[-1][-1], gridname=rg_m6m7_thick)[1] if num_unit_row % 2 == 1: end = end + laygen.get_xy(obj=ispace_sar[-1][0].template, gridname=rg_m6m7_thick)[1] input_rails_rect = [rvdd_sar_m6, rvss_sar_m6] rvdd_sar_m7, rvss_sar_m7 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M7_', layer=laygen.layers['metal'][7], gridname=rg_m6m7_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=end, offset_start_index=1, offset_end_index=0) for _idx, _vdd in enumerate(rvdd_sar_m6): xy0 = laygen.get_xy(obj=_vdd, gridname=rg_m5m6_thick) laygen.pin(name='VDD_M6' + str(_idx), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDD') for _idx, _vdd in enumerate(rvss_sar_m6): xy0 = laygen.get_xy(obj=_vdd, gridname=rg_m5m6_thick) laygen.pin(name='VSS_M6' + str(_idx), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS') # end = laygen.get_xy(obj = ispace_sar[-1][0], gridname=rg_m7m8_thick)[0]\ +laygen.get_xy(obj = ispace_sar[-1][0].template, gridname=rg_m7m8_thick)[0] input_rails_rect = [rvdd_sar_m7, rvss_sar_m7] rvdd_sar_m6, rvss_sar_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M8_', layer=laygen.layers['metal'][8], gridname=rg_m7m8_thick, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=end, offset_start_index=0, offset_end_index=0)