Exemple #1
0
    def add_wafer_outline(self):        
        """
        Create Wafer Outline
        """
        outline=Cell('WAF_OLINE')
        for l in self.cell_layers:
            circ=Circle((0, 0), self.wafer_r, 100, layer=l)
            outline.add(circ)
#            outline.add(Disk(l, (0,0), self.wafer_r, self.wafer_r-10))
        self.add(outline)
Exemple #2
0
 def add_orientation_text(self):
     """
     Create Orientation Label
     """
     tblock = Cell('WAF_ORI_TEXT')
     for l in self.cell_layers:
         for (t, pt) in self.o_text.iteritems():
             txt=Label(t, 1000, layer=l)
             bbox=txt.bounding_box
             width=np.array([1,0]) * (bbox[1,0]-bbox[0,0])
             offset=width * (-1 if pt[0]<0 else 0)
             txt.translate(np.array(pt) + offset)
             tblock.add(txt)
     self.add(tblock)
Exemple #3
0
def AlignmentMarks(styles, layers=1):
    """
    Create alignment marks.

    :param styles: a character, or a seq of characters indicating the style of
        mark(s) desired
    :param layers: an integer or a list of integers of layer(s) on which to
        place the mark of the corresponding entry in ``styles``
    :returns: A cell with the requested marks
    
    Example::
        
        # Make matching marks on layers 1 and 2
        AlignmentMarks(('A', 'C'), (1,2))        

    The marks are stored in the file CONTACTALIGN.GDS         
    
    A:(layer1):    300 x 300 um
    B:(layer2):
    C:(layer3): 600x400um
    """

    if isinstance(styles, numbers.Number): styles=[styles]
    if isinstance(layers, numbers.Number):
        layers=[layers]*len(styles)
    else:
        if len(layers)!=len(styles):
            raise ValueError('Styles and layers must have same length.')

    styles_dict={'A':1, 'B':2, 'C':3}

    cell=Cell('CONT_ALGN')

    path,_=os.path.split(__file__)
    fname=os.path.join(path, 'resources', 'ALIGNMENT.GDS')
    imp=GdsImport(fname)

    for (s,l) in zip(styles, layers):
        style=styles_dict[s]
        for e in imp['CONTACTALIGN'].elements:
            if e.layer==style:
                new_e=e.copy()
                new_e.layer=l
                cell.add(new_e)

    return cell
Exemple #4
0
def Verniers(styles, layers=1):
    """
    Create vernier alignment tools.
    
    :param styles: a character 'A' or 'B', or a list of characters indicating
        the style of mark(s) desired
    :param layers: an integer or a list of integers of layer(s) on which to
        place the mark of the corresponding entry in ``styles``
    :returns: A cell with the requested marks
    
    Example::
        
        #Make a pair of matching verniers on layers 1 and 2
        ver = Verniers(('A', 'B'), (1,2)) 
    
    The marks are stored in the file VERNIERS.GDS     

    215 x 203 um
    """

    if isinstance(styles, numbers.Number): styles=[styles]
    if isinstance(layers, numbers.Number):
        layers=[layers]*len(styles)
    else:
        if len(layers)!=len(styles):
            raise ValueError('Styles and layers must have same length.')

    styles_dict={'A':1, 'B':2, 'C':2}

    cell=Cell('VERNIERS')

    path,_=os.path.split(__file__)
    fname=os.path.join(path, 'resources', 'ALIGNMENT.GDS')
    imp=GdsImport(fname)

    for (s,l) in zip(styles, layers):
        style=styles_dict[s]
        for e in imp['VERNIERS'].elements:
            if e.layer==style:
                new_e=e.copy()
                new_e.layer=l
                cell.add(new_e)

    return cell
Exemple #5
0
 def add_dicing_marks(self):
     """
     Create dicing marks
     """
     
     width=100./2
     r=self.wafer_r
     rng=np.floor(self.wafer_r/self.block_size).astype(int)
     dmarks=Cell('DIC_MRKS')
     for l in self.cell_layers:                
         for x in np.arange(-rng[0], rng[0]+1)*self.block_size[0]:
             y=np.sqrt(r**2-x**2)
             vm=Rectangle((x-width, y), (x+width, -y), layer=l)
             dmarks.add(vm)
         
         for y in np.arange(-rng[1], rng[1]+1)*self.block_size[1]:
             x=np.sqrt(r**2-y**2)
             hm=Rectangle((x, y-width), (-x, y+width), layer=l)
             dmarks.add(hm)
     self.add(dmarks)
Exemple #6
0
    def add_aligment_marks(self):
        """
        Create alignment marks on all active layers
        """
        d_layers=self.cell_layers
        styles=['A' if i%2 else 'C' for i in range(len(d_layers))]            
        am = AlignmentMarks(styles, d_layers)
        ver = Verniers(styles, d_layers)
        mag = 10.

        mblock = Cell('WAF_ALGN_BLKS')
        mblock.add(am, magnification=mag)
        mblock.add(am, origin=(2300, -870))
        mblock.add(ver, origin=(1700, -1500), magnification=3)
        mblock.add(ver, origin=(2000, -1200))
        mblock.add(ver, origin=(2500, -1200))

        for pt in self.align_pts:
            offset=np.array([3000, 2000]) * np.sign(pt)            
            self.add(mblock, origin=pt + offset)
Exemple #7
0
class Wafer_GridStyle(Cell):
    """
    The base wafer style consisting of blocks of patterned features.
    
    :param name: The name of the new wafer cell
    :param cells:  a list of cells that will be tiled to fill the blocks
                   the cells will be cycled until all blocks are filled.
    :block_gap: the distance to leave between blocks               
    :returns: A new wafer ``Cell``        

    Spacing between cells in a block is determined automatically based on the cell
    bounding box, or by using the attribute cell.spacing if it is available.

    """

    #wafer radius (in um)
    wafer_r = None
    
    #the block size in um
    block_size = None    
    
    #the placement of the wafer alignment points
    align_pts = None
    
    def __init__(self, name, cells=None, block_gap=400):
        
        Cell.__init__(self, name)

        self.cells=cells
        self.cell_layers=self._cell_layers()
        self._label=None

        self.edge_gap=block_gap/2.        
        
    def _cell_layers(self):
        """
        A list of all active layers in ``cells``
        """
        cell_layers=set()
        for c in self.cells:
            if isinstance(c, Cell):
                cell_layers |= set(c.get_layers())
            else:
                for s in c:
                    cell_layers |= set(s.get_layers())
        return list(cell_layers)        

    def add_aligment_marks(self):
        """
        Create alignment marks on all active layers
        """
        d_layers=self.cell_layers
        styles=['A' if i%2 else 'C' for i in range(len(d_layers))]            
        am = AlignmentMarks(styles, d_layers)
        ver = Verniers(styles, d_layers)
        mag = 10.

        mblock = Cell('WAF_ALGN_BLKS')
        mblock.add(am, magnification=mag)
        mblock.add(am, origin=(2300, -870))
        mblock.add(ver, origin=(1700, -1500), magnification=3)
        mblock.add(ver, origin=(2000, -1200))
        mblock.add(ver, origin=(2500, -1200))

        for pt in self.align_pts:
            offset=np.array([3000, 2000]) * np.sign(pt)            
            self.add(mblock, origin=pt + offset)

    def add_orientation_text(self):
        """
        Create Orientation Label
        """
        tblock = Cell('WAF_ORI_TEXT')
        for l in self.cell_layers:
            for (t, pt) in self.o_text.iteritems():
                txt=Label(t, 1000, layer=l)
                bbox=txt.bounding_box
                width=np.array([1,0]) * (bbox[1,0]-bbox[0,0])
                offset=width * (-1 if pt[0]<0 else 0)
                txt.translate(np.array(pt) + offset)
                tblock.add(txt)
        self.add(tblock)

    def add_dicing_marks(self):
        """
        Create dicing marks
        """
        
        width=100./2
        r=self.wafer_r
        rng=np.floor(self.wafer_r/self.block_size).astype(int)
        dmarks=Cell('DIC_MRKS')
        for l in self.cell_layers:                
            for x in np.arange(-rng[0], rng[0]+1)*self.block_size[0]:
                y=np.sqrt(r**2-x**2)
                vm=Rectangle((x-width, y), (x+width, -y), layer=l)
                dmarks.add(vm)
            
            for y in np.arange(-rng[1], rng[1]+1)*self.block_size[1]:
                x=np.sqrt(r**2-y**2)
                hm=Rectangle((x, y-width), (-x, y+width), layer=l)
                dmarks.add(hm)
        self.add(dmarks)

    def add_wafer_outline(self):        
        """
        Create Wafer Outline
        """
        outline=Cell('WAF_OLINE')
        for l in self.cell_layers:
            circ=Circle((0, 0), self.wafer_r, 100, layer=l)
            outline.add(circ)
#            outline.add(Disk(l, (0,0), self.wafer_r, self.wafer_r-10))
        self.add(outline)

    def add_blocks(self):
        """
        Create blocks and add them to he wafer Cell
        """
        self.manifest=''
        for (i, pt) in enumerate(self.block_pts):
            cell=self.cells[i % len(self.cells)]
            origin = pt*self.block_size

            prefix=self.blockcols[pt[0]]+self.blockrows[pt[1]]
            
            if isinstance(cell, Cell):
                cell_name=prefix+cell.name
                try:
                    spacing = cell.spacing
                except AttributeError:
                    spacing = None
                block=Block(cell_name, cell, self.block_size, edge_gap=self.edge_gap, prefix=prefix+'_', spacing = spacing)
                self.manifest+='%2d\t%s\t%s\t(%.2f, %.2f)\n' % ((i, prefix, cell.name)+tuple(origin))

            else:
                cell_name=prefix + cell[0].name
                block=RangeBlock_1D(cell_name, cell, self.block_size, edge_gap=self.edge_gap, prefix=prefix+'_')
                self.manifest+='%2d\t%s\t%s\t(%.2f, %.2f)\n' % ((i, prefix, cell[0].name)+tuple(origin))

            self.add(block, origin=origin)

    def _place_blocks(self):
        """
        Create the list of valid block sites based on block size and wafer diam.
        """        
        ind_max=np.floor(self.wafer_r/self.block_size).astype(int)

        self.block_pts=[]        
        for x in range(-ind_max[0], ind_max[0]):
            for y in range(-ind_max[1], ind_max[1]):
                origin=np.array([x,y])
                flag=True
                for corner in np.array([[0,0], [1,0], [1,1], [0,1]]):
                    lsq=(((origin+corner)*self.block_size)**2).sum()
                    if lsq > self.wafer_r**2:
                        flag=False
                        break
                
                if flag:
                    self.block_pts.append([x,y])
        
        #String prefixes to associate with each row/column index
        xs, ys=set(), set()
        for p in self.block_pts:
            xs.add(p[0])
            ys.add(p[1])

        xs=sorted(list(xs))
        self.blockcols=dict(zip(xs, [string.uppercase[i] for i,x in enumerate(xs)]))
        ys=sorted(list(ys))
        self.blockrows=dict(zip(ys, [string.digits[i] for i,y in enumerate(ys)]))
                
    def add_label(self, label):
        """
        Create a label
        """
        if self._label is None:
            self._label=Cell(self.name+'_LBL')
            self.add(self._label)
        else:
            self._label.elements=[]
        
        for l in self._cell_layers():
            txt=Label(label, 1000, layer=l)
            bbox=txt.bounding_box
            offset=np.array([0,2]) * self.block_size - bbox[0] + 200
            txt.translate(offset)        
            self._label.add(txt)