blob: 7e87e16347891de70e8f32154e2a94254f0afb71 [file] [log] [blame]
########################################################################################################################
# Copyright 2022 Mabrains Company LLC
#
# Licensed under the LGPL v2.1 License (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
########################################################################################################################
## Mabrains Via Generator for Skywaters 130nm
########################################################################################################################
from .layers_definiations import *
import pya
import math
import pandas as pd
"""
Mabrains Via Generator for Skywaters 130nm
"""
class ViaGenerator(pya.PCellDeclarationHelper):
"""
Mabrains Via Generator for Skywaters 130nm
"""
layers = ["metal1","metal2","metal3","metal4","metal5"]
def __init__(self):
## Initialize super class.
super(ViaGenerator, self).__init__()
# declare the parameters
#self.param("ls", self.TypeLayer, "Starting Layer", default=pya.LayerInfo(1, 0))
#self.param("le", self.TypeLayer, "Ending Layer", default=pya.LayerInfo(1, 0))
self.param("metal", self.TypeString, "Choose metal type AL or CU", default="AL")
ending_layer = self.param("ending_metal",self.TypeString,"choose the ending material",default = "metal1")
ending_layer.add_choice("metal1", "l_met1")
ending_layer.add_choice("metal2", "l_met2")
ending_layer.add_choice("metal3", "l_met3")
ending_layer.add_choice("metal4", "l_met4")
ending_layer.add_choice("metal5", "l_met5")
self.param("width", self.TypeDouble, "width", hidden = True)
self.param("height", self.TypeDouble, "height", hidden = True)
self.param("metal", self.TypeString, "Choose metal type AL or CU", default="AL")
self.param("via_type", self.TypeString, "Choose via type", default="via")
#self.param("via", self.TypeLayer, "via_layer", default = pya.LayerInfo(via_lay_num,via_lay_dt), hidden = True)
# Below shows how to create hidden parameter is used to determine whether the radius has changed
# or the "s" handle has been moved
## self.param("ru", self.TypeDouble, "Radius", default = 0.0, hidden = True)
## self.param("rd", self.TypeDouble, "Double radius", readonly = True)
def number_spc_contacts(self, box_width, min_enc, cont_spc, cont_width):
""" Calculate number of cantacts in a given dimensions and the free space for symmetry.
By getting the min enclosure,the width of the box,the width of the cont. or via
and the spacing between cont. or via
Parameters
----------
box_width : double
The length you place the via or cont. in
min_enc : double
the spacing between the edge of the box and the first via or cont.
cont_spc : double
the spacing between different via's or cont
cont_width: double
the cont. or via width in the same direction
"""
spc_cont = box_width - 2 * min_enc
num_cont = int((spc_cont + cont_spc) / (cont_width + cont_spc))
free_spc = box_width - (num_cont * cont_width + (num_cont - 1) * cont_spc)
return num_cont, free_spc
def display_text_impl(self):
# Provide a descriptive text for the cell
return "(" + self.via_type + " metal = "+self.metal +")"
def coerce_parameters_impl(self):
# We employ coerce_parameters_impl to decide whether the handle or the
# numeric parameter has changed (by comparing against the effective
# radius ru) and set ru to the effective radius. We also update the
# numerical value or the shape, depending on which on has not changed.
pass
def can_create_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we can use any shape which
# has a finite bounding box
return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path()
def parameters_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
self.width = self.shape.bbox().width()
self.height = self.shape.bbox().height()
#global layer_number = self.layout.get_info(self.layer).layer
def transformation_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
return pya.Trans(self.shape.bbox().p1)
def produce_impl(self):
ru_dbu = 1000
# compute the circle
#pts = []
#da = math.pi * 2 / 4
#for i in range(0, 4):
#pts.append(pya.Point.from_dpoint(pya.DPoint(ru_dbu * math.cos(i * da), ru_dbu * math.sin(i * da))))
l_met1 = self.layout.layer(met1_lay_num, met1_lay_dt)
l_met2 = self.layout.layer(met2_lay_num, met2_lay_dt)
l_met3 = self.layout.layer(met3_lay_num, met3_lay_dt)
l_met4 = self.layout.layer(met4_lay_num, met4_lay_dt)
l_met5 = self.layout.layer(met5_lay_num, met5_lay_dt)
self.cell.shapes(l_met1).insert(pya.Box(0,0,self.width,self.height))
# create the shape
l_via = self.layout.layer(via_lay_num, via_lay_dt)
l_via2 = self.layout.layer(via2_lay_num, via2_lay_dt)
l_via3 = self.layout.layer(via3_lay_num, via3_lay_dt)
l_via4 = self.layout.layer(via4_lay_num, via4_lay_dt)
AL_via = pya.Box(0,0,0.15*ru_dbu,0.15*ru_dbu)
AL_via2 = pya.Box(0,0,0.2*ru_dbu,0.2*ru_dbu)
AL_via3 = pya.Box(0,0,0.2*ru_dbu,0.2*ru_dbu)
AL_via4 = pya.Box(0,0,0.8*ru_dbu,0.8*ru_dbu)
print(self.ending_metal)
CU_via = pya.Box(0,0,0.18*ru_dbu,0.18*ru_dbu)
if self.metal == "CU":
self.cell.shapes(l_via).insert(CU_via)
else:
if self.via_type == "via":
self.cell.shapes(l_via).insert(AL_via)
elif self.via_type == "via2":
self.cell.shapes(l_via2).insert(AL_via2)
elif self.via_type == "via3":
self.cell.shapes(l_via3).insert(AL_via3)
else :
self.cell.shapes(l_via4).insert(AL_via4)