blob: 780e384aa5f5c8733dedabc0e4b4471087510149 [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.
##
########################################################################################################################
##
# This file is authored by:
# - <Mina Maksimous> <mina_maksimous@mabrains.com>
##
########################################################################################################################
from .layers_definiations import *
import pya
class mimcap():
mimcap_drawing_offest = 0.5
metal3_margin_right = 0.995
mimcap_enc_metal4 = 0.195
met4_side_overlap = 0.005
met4_side_width = 0.48
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 __init__(self, layout, w, l, pin0='p0', pin1='n0',connection_labels=1):
self.layout = layout
self.l_capm = self.layout.layer(capm_lay_num, capm_lay_dt)
self.l_met3 = self.layout.layer(met3_lay_num, met3_lay_dt)
self.l_met4 = self.layout.layer(met4_lay_num, met4_lay_dt)
self.l_met4_label = self.layout.layer(
met4_label_lay_num, met4_label_lay_dt)
self.l_via3 = self.layout.layer(via3_lay_num, via3_lay_dt)
self.l_prbndry = self.layout.layer(prbndry_lay_num, prbndry_lay_dt)
self.percision = 1/self.layout.dbu
self.cell = self.layout.create_cell(
"sky130_fd_pr__cap_mim_m3_1_w"+str(w)+"_l"+str(l))
self.w = w * self.percision
self.l = l * self .percision
self.pin0 = pin0
self.pin1 = pin1
self.connection_labels=connection_labels
def draw_vias(self, box, via3_cell):
via3_size = 0.2*self.percision
met_via3_enc_1 = 0.065*self.percision
met_via3_enc_2 = 0.09*self.percision
via3_spc = 0.2*self.percision
AL_via3 = pya.Box(0, 0, via3_size, via3_size)
# via3_cell = self.layout.create_cell("via3")
via3_cell.shapes(self.l_via3).insert(AL_via3)
num_via3_1, via3_free_spc_1 = self.number_spc_contacts(
box.width(), met_via3_enc_1, via3_spc, via3_size)
num_via3_2, via3_free_spc_2 = self.number_spc_contacts(
box.height(), met_via3_enc_2, via3_spc, via3_size)
via3_arr = pya.CellInstArray(via3_cell.cell_index(), pya.Trans(
pya.Point(box.p1.x+via3_free_spc_1 / 2, box.p1.y + via3_free_spc_2 / 2)),
pya.Vector(via3_spc + via3_size, 0),
pya.Vector(0, via3_spc + via3_size),
num_via3_1, num_via3_2)
return via3_arr
def draw_cap(self):
mimcap_box = pya.Box(mimcap.mimcap_drawing_offest*self.percision,
mimcap.mimcap_drawing_offest*self.percision,
mimcap.mimcap_drawing_offest*self.percision+self.w,
mimcap.mimcap_drawing_offest*self.percision+self.l)
self.cell.shapes(self.l_capm).insert(mimcap_box)
self.met4_center_box = mimcap_box.enlarge(-1*mimcap.mimcap_enc_metal4*self.percision,
-1*mimcap.mimcap_enc_metal4*self.percision)
self.cell.shapes(self.l_met4).insert(self.met4_center_box)
met3_box = pya.Box(0, 0,
mimcap.mimcap_drawing_offest*self.percision +
self.w+mimcap.metal3_margin_right*self.percision,
2*mimcap.mimcap_drawing_offest*self.percision+self.l)
self.cell.shapes(self.l_met3).insert(met3_box)
pin0_text = pya.Text(self.pin0, self.met4_center_box.center().x,
self.met4_center_box.center().y)
prbndry_box = pya.Box(0, 0,
2*mimcap.mimcap_drawing_offest*self.percision+self.w,
2*mimcap.mimcap_drawing_offest*self.percision+self.l)
self.cell.shapes(self.l_prbndry).insert(prbndry_box)
self.met4_side_box = pya.Box(prbndry_box.p2.x-mimcap.met4_side_overlap*self.percision,
prbndry_box.p1.y + 0.06*self.percision,
prbndry_box.p2.x-mimcap.met4_side_overlap *
self.percision+mimcap.met4_side_width*self.percision,
prbndry_box.p2.y - 0.06*self.percision)
pin1_text = pya.Text(self.pin1, self.met4_side_box.center().x,
self.met4_side_box.center().y)
if self.connection_labels:
self.cell.shapes(self.l_met4_label).insert(pin0_text)
self.cell.shapes(self.l_met4_label).insert(pin1_text)
self.cell.shapes(self.l_met4).insert(self.met4_side_box)
# print('--->', self.layout.cell("via3"))
if self.layout.cell("via3") == None:
via3_cell = self.layout.create_cell("via3")
# print('--->', self.layout.cell("via3"))
else:
via3_cell = self.layout.cell("via3")
via3_arr = self.draw_vias(self.met4_center_box, via3_cell)
self.cell.insert(via3_arr)
via3_arr = self.draw_vias(self.met4_side_box, via3_cell)
self.cell.insert(via3_arr)
# For correct drc on magic
self.cell.flatten(1)
return self.cell