Layout script for NAND gate

From Center for Integrated Circuits and Devices Research (CIDR)
Jump to navigation Jump to search

[code] def draw_layout(self):

#============================================== # Extracting parameters from the __init__.py #==============================================

lch = self.params['lch'] tran_intent = self.params['tran_intent'] nmos_nf = self.params['nmos_nf'] pmos_nf = self.params['pmos_nf'] guard_ring_nf = self.params['guard_ring_nf'] pin_loc = self.params['pin_loc'] nmos_w = self.params['nmos_w'] pmos_w = self.params['pmos_w'] ntap_w = self.params['ntap_w'] ptap_w = self.params['ptap_w'] flip_well = self.params['flip_well'] show_pins = True

#============================================== # Setting up other variables in here #==============================================

   # 2 x the longest finger size

# Because we'll instance 2 transistors in one row # We added more fingers for allowance on the sides # This sets how wide the base is

   fg_tot = 2*max(nmos_nf,pmos_nf)+8 
   # Drawing parameters

# We only need 1 row of NMOS and 1 row of PMOS # Both of them are of the same transistor flavor

   nw_list = [nmos_w ] 
   n_intent_list = [tran_intent]
   pw_list = [pmos_w ]
   p_intent_list = [tran_intent]
   # Routing track definitions
   ng_tracks = [2]
   pg_tracks = [2]
   nds_tracks = [2]
   pds_tracks = [6]
   # MX means orient the gate up

# R0 means orient the gate down # All NMOS orient up while all PMOS orient down

   n_orientations=['MX']
   p_orientations=['R0']
   top_layer=5

#============================================== # Drawing the base #==============================================

   self.draw_base(lch, fg_tot, ptap_w, ntap_w, nw_list,
                  n_intent_list, pw_list, p_intent_list,
                  ng_tracks=ng_tracks, nds_tracks=nds_tracks,
                  pg_tracks=pg_tracks, pds_tracks=pds_tracks,
                  n_orientations=n_orientations, p_orientations=p_orientations, 
                  top_layer=top_layer,
                  guard_ring_nf=guard_ring_nf)

#============================================== # Drawing transistors #============================================== # As a quick guide: # mos_type = pick 'nch' for NMOS or 'pch' for PMOS # row = row # relative to the NMOS or PMOS # start_col = starting horizontal location # source_dir = source direction. If it's 2 it points downward, if it's 0 it points upward. # drain_dir = same as source_dir # s_net = assigning source terminal name # d_net = assigning source terminal name # Simply call the self.draw_mos_conn() function to draw the transistor.

   mos_type   = 'nch'
   row        = 0
   start_col  = 3
   nf         = nmos_nf
   source_dir = 2
   drain_dir  = 0
   s_net      = 'X'
   d_net      = 'Q'
   nmos0      = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
   start_col  = 3 + nmos_nf + 2
   s_net      = 'VSS'
   d_net      = 'X'
   nmos1      = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
   mos_type   = 'pch'
   start_col  = 3
   nf         = pmos_nf
   source_dir = 0
   drain_dir  = 2
   s_net      = 'VDD'
   d_net      = 'Q'
   pmos0      = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
   start_col  = 3 + pmos_nf + 2
   pmos1      = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
      
   #==============================================

# Routing proper #==============================================

   # Gate routing
   tid_A_G     = self.make_track_id('nch', row_idx=0, tr_type='g', tr_idx=-2, width=1)
   gate_A_warr = self.connect_to_tracks([nmos0['g'],pmos0['g']], tid_A_G)
   self.add_pin(self.get_pin_name('A'), gate_A_warr, show=show_pins)
   tid_B_G     = self.make_track_id('nch', row_idx=0, tr_type='g', tr_idx=-2, width=1)
   gate_B_warr = self.connect_to_tracks([nmos1['g'],pmos1['g']], tid_B_G)
   self.add_pin(self.get_pin_name('B'), gate_B_warr, show=show_pins)
   # Drain routings
   tid_P_D      = self.make_track_id('pch', row_idx=0, tr_type='ds', tr_idx=0, width=1)
   drain_P_warr = self.connect_to_tracks([pmos0['d'], pmos1['d']], tid_P_D)
   tid_N_D      = self.make_track_id('nch', row_idx=0, tr_type='ds', tr_idx=0, width=1)
   drain_N_warr = self.connect_to_tracks(nmos0['d'], tid_N_D)
   # Setting a horizontal track
   # Get location of vertical track
   loc = (drain_N_warr.get_bbox_array(self.grid).left + drain_N_warr.get_bbox_array(self.grid).right/2)
   idx = self.grid.coord_to_nearest_track(layer_id=5, coord=loc)
   # Vertical track to connect drains
   ver_id = TrackID(layer_id=5, track_idx=idx, width=1)
   out_warr = self.connect_to_tracks([drain_N_warr, drain_P_warr], ver_id)
   self.add_pin(self.get_pin_name('Q'), out_warr, show=show_pins)
   # NMOS drain-source routing
   tid_N0_N1_DS = self.make_track_id('nch', row_idx=0, tr_type='ds', tr_idx=0, width=1)
   N0_N1_DS_warr = self.connect_to_tracks([nmos0['s'], nmos1['d']], tid_N0_N1_DS)
   # Connection to VSS and VDD
   self.connect_to_substrate('ptap', nmos1['s'])
   self.connect_to_substrate('ntap', pmos0['s'])
   self.connect_to_substrate('ntap', pmos1['s'])
   # Filling dummies and adding VDD and VSS pins
   ptap_wire_arrs, ntap_wire_arrs = self.fill_dummy(vss_width=6, vdd_width=6, lower=0, upper=self.bound_box.right)
   self.add_pin(self.get_pin_name('VDD'), ntap_wire_arrs, label='VDD',show=True)
   self.add_pin(self.get_pin_name('VSS'), ptap_wire_arrs, label='VSS',show=True)
   # Create schematic parameters for update
   self.sch_params = dict()
   for key in ('lch', 
           'tran_intent', 
           'nmos_nf', 
           'nmos_w', 
           'pmos_nf', 
           'pmos_w', 
           'ntap_w', 
           'ptap_w',
           'flip_well'
           ):
       self.sch_params[key] = self.params[key]
   
   sch_dummy_info = self.get_sch_dummy_info()
   self.sch_params['sch_dummy_info'] = sch_dummy_info
   self.sch_dummy_info=sch_dummy_info

[/code]