def generate_sar_wsamp(laygen, objectname_pfix, workinglib, samp_lib, space_1x_lib, sar_name, samp_name, space_1x_name, placement_grid, routing_grid_m5m6, routing_grid_m3m4_basic_thick, routing_grid_m5m6_thick, routing_grid_m5m6_thick_basic, num_inv_bb=0, num_bits=9, use_sf=False, vref_sf=False, origin=np.array([0, 0])): """generate sar with sampling frontend """ pg = placement_grid rg_m5m6 = routing_grid_m5m6 rg_m5m6_thick = routing_grid_m5m6_thick rg_m5m6_thick_basic = routing_grid_m5m6_thick_basic #for clock routing # placement # sar isar = laygen.place(name="I" + objectname_pfix + 'SAR0', templatename=sar_name, gridname=pg, xy=origin, template_libname=workinglib) # samp isamp = laygen.relplace(name="I" + objectname_pfix + 'SAMP0', templatename=samp_name, gridname=pg, refinstname=isar.name, direction='top', template_libname=samp_lib) # source follower sf_name = 'sourceFollower_diff' if use_sf == True: isf = laygen.relplace(name="I" + objectname_pfix + 'SF0', templatename=sf_name, gridname=pg, refinstname=isamp.name, direction='top', template_libname=workinglib) sf_xy = isf.xy #prboundary sar_size = laygen.templates.get_template(sar_name, libname=workinglib).size samp_size = laygen.templates.get_template(samp_name, libname=samp_lib).size sf_size = laygen.templates.get_template(sf_name, libname=workinglib).size space_size = laygen.templates.get_template(space_1x_name, libname=space_1x_lib).size size_x = sar_size[0] size_y = int((sar_size[1] + samp_size[1]) / space_size[1] + 1) * space_size[1] if use_sf == True: size_y = int((sar_size[1] + samp_size[1] + sf_size[1]) / space_size[1] + 1) * space_size[1] laygen.add_rect(None, np.array([origin, origin + np.array([size_x, size_y])]), laygen.layers['prbnd']) # template handles sar_template = laygen.templates.get_template(sar_name, workinglib) samp_template = laygen.templates.get_template(samp_name, samp_lib) sf_template = laygen.templates.get_template(sf_name, workinglib) #reference coordinates pdict_m5m6 = laygen.get_inst_pin_xy(None, None, rg_m5m6) pdict_m5m6_thick = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick) pdict_m5m6_thick_basic = laygen.get_inst_pin_xy(None, None, rg_m5m6_thick_basic) sar_pins = sar_template.pins samp_pins = samp_template.pins sf_pins = sf_template.pins #sar_xy=isar.xy[0] #samp_xy=isamp.xy[0] sar_xy = isar.xy samp_xy = isamp.xy #signal route (clk/inp/inm) #make virtual grids and route on the grids (assuming drc clearance of each block) rg_m5m6_thick_basic_temp_sig = 'route_M5_M6_thick_basic_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick_basic, gridname_output=rg_m5m6_thick_basic_temp_sig, instname=isamp.name, inst_pin_prefix=['ckout'], xy_grid_type='xgrid') pdict_m5m6_thick_basic_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_basic_temp_sig) rg_m4m5_basic_thick_temp_sig = 'route_M4_M5_basic_thick_temp_sig' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m4m5_basic_thick, gridname_output=rg_m4m5_basic_thick_temp_sig, instname=isamp.name, inst_pin_prefix=['outp', 'outn'], xy_grid_type='xgrid') pdict_m4m5_basic_thick_temp_sig = laygen.get_inst_pin_xy( None, None, rg_m4m5_basic_thick_temp_sig) #clock rclk0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['ckout'][0], xy1=pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1] - np.array([0, 1]), gridname0=rg_m5m6_thick_basic_temp_sig) laygen.via(None, pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK0'][1], rg_m5m6_thick_basic_temp_sig) laygen.via(None, pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK1'][1], rg_m5m6_thick_basic_temp_sig) #laygen.via(None,pdict_m5m6_thick_basic_temp_sig[isar.name]['CLK2'][1], rg_m5m6_thick_basic_temp_sig) #rclk0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic[isamp.name]['ckout'][0], # xy1=pdict_m5m6_thick_basic[isar.name]['CLK'][1]-np.array([0,1]), gridname0=rg_m5m6_thick_basic) #laygen.via(None,pdict_m5m6_thick_basic[isar.name]['CLK'][1], rg_m5m6_thick_basic) #frontend sig inp_y_list = [] inm_y_list = [] for pn, p in pdict_m4m5_basic_thick_temp_sig[isar.name].items(): if pn.startswith('INP'): inp_y_list.append(p[0][1]) pv = np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0][0], p[0][1] ]) laygen.via(None, pv, rg_m4m5_basic_thick_temp_sig) #laygen.via(None,p[0], rg_m5m6_thick_basic_temp_sig) if pn.startswith('INM'): inm_y_list.append(p[0][1]) pv = np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0][0], p[0][1] ]) laygen.via(None, pv, rg_m4m5_basic_thick_temp_sig) #laygen.via(None,p[0], rg_m5m6_thick_basic_temp_sig) inp_y = min(inp_y_list) inm_y = min(inm_y_list) rinp0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0], xy1=np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outp'][0][0], inp_y - 1 ]), gridname0=rg_m4m5_basic_thick_temp_sig) rinm0 = laygen.route( None, laygen.layers['metal'][5], xy0=pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0], xy1=np.array([ pdict_m4m5_basic_thick_temp_sig[isamp.name]['outn'][0][0], inm_y - 1 ]), gridname0=rg_m4m5_basic_thick_temp_sig) #rinp0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outp'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INP0'][0][0],inp_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) #rinm0 = laygen.route(None, laygen.layers['metal'][5], # xy0=pdict_m5m6_thick_basic_temp_sig[isamp.name]['outn'][0], # xy1=np.array([pdict_m5m6_thick_basic_temp_sig[isar.name]['INM0'][0][0],inm_y-1]), # gridname0=rg_m5m6_thick_basic_temp_sig) # source follower routing pdict_m4m5_thick = laygen.get_inst_pin_xy(None, None, rg_m4m5_thick) if use_sf == True: [rh0, rv0] = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5_thick[isf.name]['outp'][0], pdict_m4m5_thick[isamp.name]['inp'][0], rg_m4m5_thick) [rh0, rv0] = laygen.route_hv(laygen.layers['metal'][4], laygen.layers['metal'][5], pdict_m4m5_thick[isf.name]['outn'][0], pdict_m4m5_thick[isamp.name]['inn'][0], rg_m4m5_thick) # VDD/VSS for source follower for pn, p in samp_pins.items(): if pn.startswith('LVDD'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD1'][0], rg_m4m5_thick) if pn.startswith('RVDD'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VDD1'][0], rg_m4m5_thick) if pn.startswith('LVSS'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS1'][0], rg_m4m5_thick) if pn.startswith('RVSS'): laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS0'][0], rg_m4m5_thick) laygen.route_vh(laygen.layers['metal'][5], laygen.layers['metal'][4], pdict_m4m5_thick[isamp.name][pn][0], pdict_m4m5_thick[isf.name]['VSS1'][0], rg_m4m5_thick) #input pins (just duplicate from lower hierarchy cells) laygen.add_pin('CLK', 'CLK', samp_xy + samp_pins['ckin']['xy'], samp_pins['ckin']['layer']) if use_sf == False: laygen.add_pin('INP', 'INP', samp_xy + samp_pins['inp']['xy'], samp_pins['inp']['layer']) laygen.add_pin('INM', 'INM', samp_xy + samp_pins['inn']['xy'], samp_pins['inn']['layer']) else: laygen.add_pin('INP', 'INP', sf_xy + sf_pins['inp']['xy'], sf_pins['inp']['layer']) laygen.add_pin('INM', 'INM', sf_xy + sf_pins['inn']['xy'], sf_pins['inn']['layer']) for pn, p in sf_pins.items(): if pn.startswith('Voffp'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_' + pn, 'SF_Voffp', pxy, sf_pins[pn]['layer']) if pn.startswith('Voffn'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_' + pn, 'SF_Voffn', pxy, sf_pins[pn]['layer']) if pn.startswith('bypass'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_' + pn, 'SF_bypass', pxy, sf_pins[pn]['layer']) if pn.startswith('VBIAS'): pxy = sf_xy + sf_pins[pn]['xy'] laygen.add_pin('SF_BIAS', 'SF_BIAS', pxy, sf_pins[pn]['layer']) # if pn.startswith('VBIASn'): # pxy = sf_xy + sf_pins[pn]['xy'] # laygen.add_pin('SF_BIASn', 'SF_BIASn', pxy, sf_pins[pn]['layer']) if vref_sf == True: laygen.add_pin('VREF_SF_BIAS', 'VREF_SF_BIAS', sar_xy + sar_pins['SF_VBIAS']['xy'], sar_pins['SF_VBIAS']['layer']) laygen.add_pin('VREF_SF_bypass', 'VREF_SF_bypass', sar_xy + sar_pins['SF_bypass']['xy'], sar_pins['SF_bypass']['layer']) laygen.add_pin('OSP', 'OSP', sar_xy + sar_pins['OSP']['xy'], sar_pins['OSP']['layer']) laygen.add_pin('OSM', 'OSM', sar_xy + sar_pins['OSM']['xy'], sar_pins['OSM']['layer']) for pn, p in sar_pins.items(): if pn.startswith('VREF<0>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<0>', pxy, sar_pins[pn]['layer']) if pn.startswith('VREF<1>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<1>', pxy, sar_pins[pn]['layer']) if pn.startswith('VREF<2>'): pxy = sar_xy + sar_pins[pn]['xy'] laygen.add_pin(pn, 'VREF<2>', pxy, sar_pins[pn]['layer']) #laygen.add_pin('VREF_M5R<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5R<2>']['xy'], sar_pins['VREF_M5R<2>']['layer']) #laygen.add_pin('VREF_M5R<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5R<1>']['xy'], sar_pins['VREF_M5R<1>']['layer']) #laygen.add_pin('VREF_M5R<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5R<0>']['xy'], sar_pins['VREF_M5R<0>']['layer']) #laygen.add_pin('VREF_M5L<2>', 'VREF<2>', sar_xy+sar_pins['VREF_M5L<2>']['xy'], sar_pins['VREF_M5L<2>']['layer']) #laygen.add_pin('VREF_M5L<1>', 'VREF<1>', sar_xy+sar_pins['VREF_M5L<1>']['xy'], sar_pins['VREF_M5L<1>']['layer']) #laygen.add_pin('VREF_M5L<0>', 'VREF<0>', sar_xy+sar_pins['VREF_M5L<0>']['xy'], sar_pins['VREF_M5L<0>']['layer']) laygen.add_pin('CKDSEL0<1>', 'CKDSEL0<1>', sar_xy + sar_pins['CKDSEL0<1>']['xy'], sar_pins['CKDSEL0<1>']['layer']) laygen.add_pin('CKDSEL0<0>', 'CKDSEL0<0>', sar_xy + sar_pins['CKDSEL0<0>']['xy'], sar_pins['CKDSEL0<0>']['layer']) laygen.add_pin('CKDSEL1<1>', 'CKDSEL1<1>', sar_xy + sar_pins['CKDSEL1<1>']['xy'], sar_pins['CKDSEL1<1>']['layer']) laygen.add_pin('CKDSEL1<0>', 'CKDSEL1<0>', sar_xy + sar_pins['CKDSEL1<0>']['xy'], sar_pins['CKDSEL1<0>']['layer']) #laygen.add_pin('EXTCLK', 'EXTCLK', sar_xy+sar_pins['EXTCLK']['xy'], sar_pins['EXTCLK']['layer']) laygen.add_pin('EXTSEL_CLK', 'EXTSEL_CLK', sar_xy + sar_pins['EXTSEL_CLK']['xy'], sar_pins['EXTSEL_CLK']['layer']) #output pins (just duplicate from lower hierarchy cells) for i in range(num_bits): pn = 'ADCOUT' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) laygen.add_pin('CLKO0', 'CLKO', sar_xy + sar_pins['CLKOUT0']['xy'], sar_pins['CLKOUT0']['layer']) laygen.add_pin('CLKO1', 'CLKO', sar_xy + sar_pins['CLKOUT1']['xy'], sar_pins['CLKOUT1']['layer']) #laygen.add_pin('CLKO2', 'CLKO', sar_xy+sar_pins['CLKOUT2']['xy'], sar_pins['CLKOUT2']['layer']) #probe pins laygen.add_pin('CLK0', 'ICLK', sar_xy + sar_pins['CLK0']['xy'], sar_pins['CLK0']['layer']) laygen.add_pin('CLK1', 'ICLK', sar_xy + sar_pins['CLK1']['xy'], sar_pins['CLK1']['layer']) #laygen.add_pin('CLK2', 'ICLK', sar_xy+sar_pins['CLK2']['xy'], sar_pins['CLK2']['layer']) laygen.add_pin('CLKPRB_SAMP', 'CLKPRB_SAMP', samp_xy + samp_pins['ckpg']['xy'], samp_pins['ckpg']['layer']) #laygen.add_pin('CLKPRB_SAR', 'CLKPRB_SAR', sar_xy+sar_pins['CLKPRB']['xy'], sar_pins['CLKPRB']['layer']) laygen.add_pin('SAMPP', 'SAMPP', sar_xy + sar_pins['SAINP']['xy'], sar_pins['SAINP']['layer']) laygen.add_pin('SAMPM', 'SAMPM', sar_xy + sar_pins['SAINM']['xy'], sar_pins['SAINM']['layer']) laygen.add_pin('SAOP', 'SAOP', sar_xy + sar_pins['SAOP']['xy'], sar_pins['SAOP']['layer']) laygen.add_pin('SAOM', 'SAOM', sar_xy + sar_pins['SAOM']['xy'], sar_pins['SAOM']['layer']) laygen.add_pin('SARCLK', 'SARCLK', sar_xy + sar_pins['SARCLK']['xy'], sar_pins['SARCLK']['layer']) laygen.add_pin('SARCLKB', 'SARCLKB', sar_xy + sar_pins['SARCLKB']['xy'], sar_pins['SARCLKB']['layer']) #laygen.add_pin('COMPOUT', 'COMPOUT', sar_xy+sar_pins['COMPOUT']['xy'], sar_pins['COMPOUT']['layer']) laygen.add_pin('DONE', 'DONE', sar_xy + sar_pins['DONE']['xy'], sar_pins['DONE']['layer']) laygen.add_pin('UP', 'UP', sar_xy + sar_pins['UP']['xy'], sar_pins['UP']['layer']) laygen.add_pin('PHI0', 'PHI0', sar_xy + sar_pins['PHI0']['xy'], sar_pins['PHI0']['layer']) for i in range(num_bits): pn = 'ZP' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'ZMID' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'ZM' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'SB' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) for i in range(num_bits - 1): pn = 'VOL' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) pn = 'VOR' + '<' + str(i) + '>' laygen.add_pin(pn, pn, sar_xy + sar_pins[pn]['xy'], sar_pins[pn]['layer']) #VDD/VSS pin vddcnt = 0 vsscnt = 0 for p in pdict_m5m6[isar.name]: if p.startswith('VDD'): xy0 = pdict_m5m6_thick[isar.name][p] laygen.pin(name='VDDSAR' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VDDSAR') vddcnt += 1 if p.startswith('VSS'): xy0 = pdict_m5m6_thick[isar.name][p] laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS:') #laygen.pin(name='VSSSAR' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick, netname='VSS') vsscnt += 1 #extract VDD/VSS grid from samp and make power pins rg_m5m6_thick_temp_samp = 'route_M5_M6_thick_temp_samp' laygenhelper.generate_grids_from_inst( laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_thick_temp_samp, instname=isamp.name, inst_pin_prefix=['VDD', 'VSS', 'samp_body'], xy_grid_type='ygrid') pdict_m5m6_thick_temp_samp = laygen.get_inst_pin_xy( None, None, rg_m5m6_thick_temp_samp) vddcnt = 0 vsscnt = 0 bodycnt = 0 for p in pdict_m5m6_thick_temp_samp[isamp.name]: if p.startswith('VDD'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='VDDSAMP' + str(vddcnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VDDSAMP') vddcnt += 1 if p.startswith('VSS'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS:') #laygen.pin(name='VSSSAMP' + str(vsscnt), layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='VSS') vsscnt += 1 if p.startswith('samp_body'): xy0 = pdict_m5m6_thick_temp_samp[isamp.name][p] laygen.pin(name='samp_body', layer=laygen.layers['pin'][6], xy=xy0, gridname=rg_m5m6_thick_temp_samp, netname='samp_body') bodycnt += 1 # VBB pdict_m3m4 = laygen.get_inst_pin_xy(None, None, rg_m3m4_basic_thick) if not num_inv_bb == 0: rvbb_m3 = [] for p in pdict_m3m4[isar.name]: if p.startswith('VBB') and p.endswith('0'): rvbb_m3.append(pdict_m3m4[isar.name][p]) # laygen.pin(name='bottom_body'+str(p), layer=laygen.layers['pin'][3], xy=pdict_m3m4[isar.name][p], gridname=rg_m3m4, netname='bottom_body') rvbb_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_basic_thick, netnames=['bottom_body'], direction='x', input_rails_xy=[rvbb_m3], generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rvbb_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['bottom_body'], direction='y', input_rails_rect=rvbb_m4, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-2) rvbb_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['metal'][6], gridname=rg_m5m6_thick, netnames=['bottom_body'], direction='x', input_rails_rect=rvbb_m5, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) num_m6 = len(rvbb_m6[0]) for i in range(num_m6): if i % 2 == 1: rvbb_m6[0].remove(rvbb_m6[0][num_m6 - i - 1]) print(rvbb_m6[0]) rvbb_m7 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M7_', layer=laygen.layers['pin'][7], gridname=rg_m6m7_thick, netnames=['bottom_body'], direction='y', input_rails_rect=rvbb_m6, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0)
def generate_tisaradc_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_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_tisaradc_space2(laygen, objectname_pfix, tisar_libname, space_libname, tisar_name, space_name, placement_grid, routing_grid_m3m4_thick, routing_grid_m4m5_thick, routing_grid_m5m6_thick, origin=np.array([0, 0])): """generate tisar space """ pg = placement_grid ttisar = laygen.templates.get_template(tisar_name, libname=tisar_libname) tspace = laygen.templates.get_template(space_name, libname=space_libname) sar_pins = ttisar.pins tbnd_bottom = laygen.templates.get_template('boundary_bottom') tbnd_bleft = laygen.templates.get_template('boundary_bottomleft') space_xy = np.array([tspace.size[0], ttisar.size[1]]) laygen.add_rect( None, np.array([ origin, origin + space_xy + 2 * tbnd_bleft.size[0] * np.array([1, 0]) ]), laygen.layers['prbnd']) num_space_tot = int( (ttisar.size[1] - 2 * tbnd_bottom.size[1]) / tspace.size[1]) tbnd_bleft_size = tbnd_bleft.size #VDD/VSS/VREF integration rvddclkd = [] rvddsamp = [] rvddsar = [] rvddsar_upper = [] rvref0 = [] rvref1 = [] rvref2 = [] rvssclkd = [] rvsssamp = [] rvsssar = [] rvsssar_upper = [] vddclkd_xy = [] vddsamp_xy = [] vddsar_xy = [] vddsar_upper_xy = [] vssclkd_xy = [] vsssamp_xy = [] vsssar_xy = [] vsssar_upper_xy = [] y_vddsar_max = 0 y_vddsar_lower_max = 0 y_vddsamp_min = 500000 y_vddsamp_max = 0 y_vddclkd_min = 500000 y_vref0 = sar_pins['VREF0<0>']['xy'][0][1] #categorize vdd pins and figure out thresholds for pn, p in sar_pins.items(): ''' if pn.startswith('VDDCLKD'): pxy=np.array([[0, sar_pins[pn]['xy'][0][1]], [2*tbnd_bleft_size[0]+space_xy[0], sar_pins[pn]['xy'][1][1]]]) rvddclkd.append(laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pxy[1][1]<y_vddclkd_min: y_vddclkd_min=pxy[1][1] vddclkd_xy.append(pxy) ''' if pn.startswith('VDDSAMP'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) rvddsamp.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pxy[1][1] < y_vddsamp_min: y_vddsamp_min = pxy[1][1] if pxy[1][1] > y_vddsamp_max: y_vddsamp_max = pxy[1][1] vddsamp_xy.append(pxy) if pn.startswith('VDDSAR'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) if pxy[0][1] > y_vref0: rvddsar_upper.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vddsar_upper_xy.append(pxy) else: rvddsar.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vddsar_xy.append(pxy) if pxy[1][1] > y_vddsar_lower_max: y_vddsar_lower_max = pxy[1][1] if pxy[1][1] > y_vddsar_max: y_vddsar_max = pxy[1][1] if pn.startswith('VREF'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) if pn.endswith('<0>'): rvref0.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pn.endswith('<1>'): rvref1.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) if pn.endswith('<2>'): rvref2.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) y_vss_th = 0.5 * (y_vddsar_max + y_vddsamp_min ) #find out threshold (sar/samp) #y_vss_th2=0.5*(y_vddsamp_max+y_vddclkd_min) #(samp/clkd) y_vss_th2 = 100000 for pn, p in sar_pins.items(): if pn.startswith('VSS'): pxy = np.array([[0, sar_pins[pn]['xy'][0][1]], [ 2 * tbnd_bleft_size[0] + space_xy[0], sar_pins[pn]['xy'][1][1] ]]) if pxy[0][1] > y_vss_th2: rvssclkd.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vssclkd_xy.append(pxy) elif pxy[0][1] > y_vss_th: rvsssamp.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vsssamp_xy.append(pxy) elif pxy[0][1] > y_vref0: rvsssar_upper.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vsssar_upper_xy.append(pxy) else: rvsssar.append( laygen.add_rect(None, pxy, laygen.layers['metal'][6])) vsssar_xy.append(pxy) #vddsar cap num_space_sar = int( (y_vss_th - 2 * tbnd_bottom.size[1]) / tspace.size[1]) + 4 space_origin = origin + laygen.get_template_size('boundary_bottomleft', pg) ispace_sar = [ laygen.place(name="I" + objectname_pfix + 'SPSAR0', templatename=space_name, gridname=pg, xy=space_origin, template_libname=space_libname) ] devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] for i in range(1, num_space_sar): if i % 2 == 0: ispace_sar.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_sar[-1].name, direction='top', transform='R0', template_libname=space_libname)) devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: ispace_sar.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAR' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_sar[-1].name, direction='top', transform='MX', template_libname=space_libname)) devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAR0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) #vddsamp cap num_space_samp = num_space_tot - num_space_sar - 1 space_origin = origin + laygen.get_template_size( 'boundary_bottomleft', pg) * np.array([1, (3 + 2 * num_space_sar)]) ispace_samp = [ laygen.place(name="I" + objectname_pfix + 'SPSAMP0', templatename=space_name, gridname=pg, xy=space_origin, template_libname=space_libname) ] devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] for i in range(1, num_space_samp): if i % 2 == 0: ispace_samp.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_samp[-1].name, direction='top', transform='R0', template_libname=space_libname)) devname_bnd_left += ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right += ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] else: ispace_samp.append( laygen.relplace(name="I" + objectname_pfix + 'SPSAMP' + str(i), templatename=space_name, gridname=pg, refinstname=ispace_samp[-1].name, direction='top', transform='MX', template_libname=space_libname)) devname_bnd_left += ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right += ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left += ['R0', 'MX'] transform_bnd_right += ['R0', 'MX'] m_bnd = int(space_xy[0] / tbnd_bottom.size[0]) [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BNDSAMP0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=space_origin-laygen.get_template_size('boundary_bottomleft', pg)) #vdd/vss #m3 rvdd_sar_xy_m3 = [] rvss_sar_xy_m3 = [] space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins space_origin_phy = laygen.get_inst_bbox_phygrid(ispace_sar[0].name)[0] vddcnt = 0 vsscnt = 0 for pn, p in space_pins.items(): if pn.startswith('VDD'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_sar])]) pxy[1][1] = y_vddsar_lower_max laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvdd_sar_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vddcnt += 1 if pn.startswith('VSS'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_sar])]) pxy[1][1] = y_vddsar_lower_max laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvss_sar_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vsscnt += 1 rvdd_samp_xy_m3 = [] rvss_samp_xy_m3 = [] space_template = laygen.templates.get_template(space_name, workinglib) space_pins = space_template.pins space_origin_phy = laygen.get_inst_bbox_phygrid(ispace_samp[0].name)[0] vddcnt = 0 vsscnt = 0 for pn, p in space_pins.items(): if pn.startswith('VDD'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_samp])]) laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvdd_samp_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vddcnt += 1 if pn.startswith('VSS'): pxy = space_origin_phy + np.array( [p['xy'][0], p['xy'][1] * np.array([1, num_space_samp])]) laygen.add_rect(None, pxy, laygen.layers['metal'][3]) rvss_samp_xy_m3.append( laygen.grids.get_absgrid_coord_region(gridname=rg_m3m4_thick, xy0=pxy[0], xy1=pxy[1])) vsscnt += 1 #m4 input_rails_xy = [rvdd_samp_xy_m3, rvss_samp_xy_m3] rvdd_samp_m4, rvss_samp_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_SAMP_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDDSAMP', 'VSSSAMP'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_xy = [rvdd_sar_xy_m3, rvss_sar_xy_m3] rvdd_sar_m4, rvss_sar_m4 = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_M4_SAR_', layer=laygen.layers['metal'][4], gridname=rg_m3m4_thick, netnames=['VDDSAR', 'VSSSAR'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m5 input_rails_rect = [rvdd_samp_m4, rvss_samp_m4] rvdd_samp_m5, rvss_samp_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_SAMP', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_rect = [rvdd_sar_m4, rvss_sar_m4] rvdd_sar_m5, rvss_sar_m5 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M5_SAR', layer=laygen.layers['metal'][5], gridname=rg_m4m5_thick, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m6 (extract VDD/VSS grid from tisar and make power pins) rg_m5m6_sar_vdd = 'route_M5_M6_thick_temp_tisar_sar_vdd' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_sar_vdd, xy=vddsar_xy, xy_grid_type='ygrid') input_rails_rect = [rvdd_sar_m5] [rvdd_sar_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAR_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_sar_vdd, netnames=['VDDSAR'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_sar_vss = 'route_M5_M6_thick_temp_tisar_sar_vss' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_sar_vss, xy=vsssar_xy, xy_grid_type='ygrid') input_rails_rect = [rvss_sar_m5] [rvss_sar_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAR_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_sar_vss, netnames=['VSS:'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_samp = 'route_M5_M6_thick_temp_tisar_samp_vdd' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_samp, xy=vddsamp_xy, xy_grid_type='ygrid') input_rails_rect = [rvdd_samp_m5] [rvdd_samp_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAMP_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_samp, netnames=['VDDSAMP'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) rg_m5m6_samp = 'route_M5_M6_thick_temp_tisar_samp_vss' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_samp, xy=vsssamp_xy, xy_grid_type='ygrid') input_rails_rect = [rvss_samp_m5] [rvss_samp_m6] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_SAMP_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_samp, netnames=['VSS:'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) ''' rg_m5m6_clkd='route_M5_M6_thick_temp_tisar_clkd' laygenhelper.generate_grids_from_xy(laygen, gridname_input=rg_m5m6_thick, gridname_output=rg_m5m6_clkd, xy=vddclkd_xy + vssclkd_xy, xy_grid_type='ygrid') input_rails_rect = [rvdd_samp_m5, rvss_samp_m5] [rvdd_clkd_m6, rvss_clkd_m6] = laygenhelper.generate_power_rails_from_rails_rect(laygen, routename_tag='_M6_CLKD_', layer=laygen.layers['pin'][6], gridname=rg_m5m6_clkd, netnames=['VDDSAMP', 'VSS:'], direction='x', input_rails_rect=input_rails_rect, generate_pin=True, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) ''' print(num_space_sar, num_space_samp) yamlfile_output = "adc_sar_size.yaml" #write to file with open(yamlfile_output, 'r') as stream: outdict = yaml.load(stream) outdict['num_space_sar'] = num_space_sar outdict['num_space_samp'] = num_space_samp with open(yamlfile_output, 'w') as stream: yaml.dump(outdict, stream)
def generate_samp(laygen, objectname_pfix, workinglib, placement_grid='placement_basic', routing_grid_m4m5='route_M4_M5_basic_thick', power_grid_m3m4='route_M3_M4_basic_thick', power_grid_m4m5='route_M4_M5_thick', power_grid_m5m6='route_M5_M6_thick', origin=np.array([0, 0])): """generate a sampler with clock buffers. used when AnalogMOS is not available """ #variable/cell namings pg = placement_grid rg45bt = routing_grid_m4m5 pg34bt = power_grid_m3m4 pg45t = power_grid_m4m5 pg56t = power_grid_m5m6 # placement core_origin = origin + laygen.get_xy( obj=laygen.get_template(name='boundary_bottomleft'), gridname=pg) # sampler body isamp = laygen.relplace(name=None, templatename='sarsamp_body', gridname=pg, template_libname=workinglib, transform='R0', xy=core_origin) # clock buffer if tgate == True: ibuf = laygen.relplace(name=None, templatename='sarsamp_buf', gridname=pg, refobj=isamp, direction='top', template_libname=workinglib, transform='MX') else: ibuf = laygen.relplace(name=None, templatename='sarsamp_buf', gridname=pg, refobj=isamp, direction='top', template_libname=workinglib, transform='R0') # boundaries a = laygen.get_xy(obj=laygen.get_template(name='sarsamp_body', libname=workinglib), gridname=pg)[0] b = laygen.get_xy(obj=laygen.get_template(name='boundary_bottom'), gridname=pg)[0] m_bnd = int(a / b) if tgate == True: devname_bnd_left = ['nmos4_fast_left', 'pmos4_fast_left' ] + ['pmos4_fast_left', 'nmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'pmos4_fast_right' ] + ['pmos4_fast_right', 'nmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] + ['MX', 'R0'] transform_bnd_right = ['R0', 'MX'] + ['MX', 'R0'] else: devname_bnd_left = ['nmos4_fast_left', 'nmos4_fast_left' ] + ['nmos4_fast_left', 'pmos4_fast_left'] devname_bnd_right = ['nmos4_fast_right', 'nmos4_fast_right' ] + ['nmos4_fast_right', 'pmos4_fast_right'] transform_bnd_left = ['R0', 'MX'] + ['R0', 'MX'] transform_bnd_right = ['R0', 'MX'] + ['R0', 'MX'] [bnd_bottom, bnd_top, bnd_left, bnd_right] \ = laygenhelper.generate_boundary(laygen, objectname_pfix='BND0', placement_grid=pg, devname_bottom=['boundary_bottomleft', 'boundary_bottom', 'boundary_bottomright'], shape_bottom=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_top=['boundary_topleft', 'boundary_top', 'boundary_topright'], shape_top=[np.array([1, 1]), np.array([m_bnd, 1]), np.array([1, 1])], devname_left=devname_bnd_left, transform_left=transform_bnd_left, devname_right=devname_bnd_right, transform_right=transform_bnd_right, origin=origin) # route x_center=int((laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[1][0] \ -laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[0][0])/2\ +laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[0][0]) y_top = int( laygen.get_inst_bbox(name=ibuf.name, gridname=rg45bt, sort=True)[1][1]) #in xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='IP', gridname=rg45bt, sort=True)[0] xy1 = [x_center - 3, y_top] rh0, rinp0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='IM', gridname=rg45bt, sort=True)[0] xy1 = [x_center + 3, y_top] rh0, rinn0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) #out xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='OP', gridname=rg45bt, sort=True)[0] xy1 = [x_center - 3, 0] rh0, routp0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) xy0 = laygen.get_inst_pin_xy(name=isamp.name, pinname='OM', gridname=rg45bt, sort=True)[0] xy1 = [x_center + 3, 0] rh0, routn0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) #en xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='OUT_SW', gridname=rg45bt, sort=True)[0] xy1 = laygen.get_inst_pin_xy(name=isamp.name, pinname='EN', gridname=rg45bt, sort=True)[0] rh0, rckpg0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center - 1, gridname0=rg45bt) rh0, rv0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center + 1, gridname0=rg45bt) #enb if tgate == True: xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='out_int<0>', gridname=rg45bt, sort=True)[0] xy1 = laygen.get_inst_pin_xy(name=isamp.name, pinname='ENB', gridname=rg45bt, sort=True)[0] rh0, rckint0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center - 2, gridname0=rg45bt) rh0, rv0, rh1 = laygen.route_hvh(xy0=xy0, xy1=xy1, track_x=x_center + 2, gridname0=rg45bt) #ckin xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='IN', gridname=rg45bt, sort=True)[0] xy1 = [xy0[0], y_top] rh0, rckin0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) #ckout xy0 = laygen.get_inst_pin_xy(name=ibuf.name, pinname='OUT_BUF', gridname=rg45bt, sort=True)[0] xy1 = [x_center, 0] rh0, rckout0 = laygen.route_hv(xy0=xy0, xy1=xy1, gridname0=rg45bt) # signal pins for p, r in zip(['inp', 'inn', 'outp', 'outn', 'ckin', 'ckout', 'ckpg'], [rinp0, rinn0, routp0, routn0, rckin0, rckout0, rckpg0]): laygen.pin(name=p, layer=laygen.layers['pin'][5], refobj=r, gridname=rg45bt) #vdd/vss - route #samp_m3_xy rvss_samp_m3 = [[], []] for pn, p in laygen.get_inst(isamp.name).pins.items(): if pn.startswith('VSSL'): xy = laygen.get_inst_pin_xy(name=isamp.name, pinname=pn, gridname=pg34bt, sort=True) rvss_samp_m3[0].append(xy) if pn.startswith('VSSR'): xy = laygen.get_inst_pin_xy(name=isamp.name, pinname=pn, gridname=pg34bt, sort=True) rvss_samp_m3[1].append(xy) #samp_m4 rvss_samp_m4 = [None, None] input_rails_xy = [rvss_samp_m3[0]] rvss_samp_m4[0] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_SAMPL_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-1)[0] input_rails_xy = [rvss_samp_m3[1]] rvss_samp_m4[1] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_SAMPR_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=-1)[0] #buf_m3_xy rvdd_buf_m3 = [[], []] rvss_buf_m3 = [[], []] for pn, p in laygen.get_inst(ibuf.name).pins.items(): if pn.startswith('VSSL'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvss_buf_m3[0].append(xy) if pn.startswith('VSSR'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvss_buf_m3[1].append(xy) if pn.startswith('VDDL'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvdd_buf_m3[0].append(xy) if pn.startswith('VDDR'): xy = laygen.get_inst_pin_xy(name=ibuf.name, pinname=pn, gridname=pg34bt, sort=True) rvdd_buf_m3[1].append(xy) #buf_m4 rvss_buf_m4 = [None, None] rvdd_buf_m4 = [None, None] input_rails_xy = [rvdd_buf_m3[0], rvss_buf_m3[0]] rvdd_buf_m4[0], rvss_buf_m4[ 0] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_BUFL_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VDD', 'VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) input_rails_xy = [rvdd_buf_m3[1], rvss_buf_m3[1]] rvdd_buf_m4[1], rvss_buf_m4[ 1] = laygenhelper.generate_power_rails_from_rails_xy( laygen, routename_tag='_BUFR_M4_', layer=laygen.layers['metal'][4], gridname=pg34bt, netnames=['VDD', 'VSS'], direction='x', input_rails_xy=input_rails_xy, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=1, offset_end_index=0) #m4 rvss_m4 = [ rvss_samp_m4[0] + rvss_buf_m4[0], rvss_samp_m4[1] + rvss_buf_m4[1] ] rvdd_m4 = rvdd_buf_m4 #m5 rvss_m5 = [None, None] rvdd_m5 = [None, None] input_rails_rect = [rvdd_m4[0], rvss_m4[0]] rvdd_m5[0], rvss_m5[0] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='L_M5_', layer=laygen.layers['metal'][5], gridname=pg45t, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) input_rails_rect = [rvdd_m4[1], rvss_m4[1]] rvdd_m5[1], rvss_m5[1] = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='R_M5_', layer=laygen.layers['metal'][5], gridname=pg45t, netnames=['VDD', 'VSS'], direction='y', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=None, overwrite_end_coord=None, offset_start_index=0, offset_end_index=0) #m6 input_rails_rect = [rvdd_m5[0] + rvdd_m5[1], rvss_m5[0] + rvss_m5[1]] x1 = laygen.get_inst_bbox( name=ibuf.name, gridname=pg56t)[1][0] + laygen.get_xy( obj=laygen.get_template(name='nmos4_fast_left'), gridname=pg56t)[0] rvdd_m6, rvss_m6 = laygenhelper.generate_power_rails_from_rails_rect( laygen, routename_tag='_M6_', layer=laygen.layers['metal'][6], gridname=pg56t, netnames=['VDD', 'VSS'], direction='x', input_rails_rect=input_rails_rect, generate_pin=False, overwrite_start_coord=0, overwrite_end_coord=x1, offset_start_index=0, offset_end_index=0) #trimming and pinning x1_phy = laygen.get_inst_bbox(name=ibuf.name)[1][0] + laygen.get_xy( obj=laygen.get_template(name='nmos4_fast_left'))[0] for r in rvdd_m6: r.xy1[0] = x1_phy p = laygen.pin(name='VDD_M6_' + r.name, layer=laygen.layers['pin'][6], refobj=r, gridname=pg56t, netname='VDD') p.xy1[0] = x1_phy for r in rvss_m6: r.xy1[0] = x1_phy p = laygen.pin(name='VSS_M6_' + r.name, layer=laygen.layers['pin'][6], refobj=r, gridname=pg56t, netname='VSS') p.xy1[0] = x1_phy
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_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_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)