From 4ff29181eff91dd22736a51ac7360f24c4a1debb Mon Sep 17 00:00:00 2001 From: FaragElsayed2 Date: Sun, 17 Sep 2023 10:03:18 +0300 Subject: [PATCH] Updating vias pcells for GF180MCU --- cells/klayout/pymacros/cells/draw_cap_mim.py | 3 +- cells/klayout/pymacros/cells/draw_cap_mos.py | 4 +- cells/klayout/pymacros/cells/draw_diode.py | 18 ++-- cells/klayout/pymacros/cells/draw_fet.py | 26 ++---- cells/klayout/pymacros/cells/draw_res.py | 22 ++--- cells/klayout/pymacros/cells/fet.py | 4 +- cells/klayout/pymacros/cells/via_generator.py | 91 ++++++++----------- cells/klayout/pymacros/cells/vias_gen.py | 36 ++++---- 8 files changed, 80 insertions(+), 124 deletions(-) diff --git a/cells/klayout/pymacros/cells/draw_cap_mim.py b/cells/klayout/pymacros/cells/draw_cap_mim.py index 2e7f69e1..31b7164f 100644 --- a/cells/klayout/pymacros/cells/draw_cap_mim.py +++ b/cells/klayout/pymacros/cells/draw_cap_mim.py @@ -139,7 +139,6 @@ def draw_cap_mim( c.write_gds("mim_cap_temp.gds") layout.read("mim_cap_temp.gds") - cell_name = "mim_cap_dev" os.remove("mim_cap_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) diff --git a/cells/klayout/pymacros/cells/draw_cap_mos.py b/cells/klayout/pymacros/cells/draw_cap_mos.py index 24d80977..675bbafb 100644 --- a/cells/klayout/pymacros/cells/draw_cap_mos.py +++ b/cells/klayout/pymacros/cells/draw_cap_mos.py @@ -434,7 +434,6 @@ def draw_cap_mos( # generating contacts if deepnwell == 0 and gr_imp == layer["nplus"]: - print("here") nwell_rect = c.add_ref( gf.components.rectangle( @@ -524,7 +523,6 @@ def draw_cap_mos( c.write_gds("cap_mos_temp.gds") layout.read("cap_mos_temp.gds") - cell_name = "cap_mos_dev" os.remove("cap_mos_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) diff --git a/cells/klayout/pymacros/cells/draw_diode.py b/cells/klayout/pymacros/cells/draw_diode.py index a90c8b8f..bb440b55 100644 --- a/cells/klayout/pymacros/cells/draw_diode.py +++ b/cells/klayout/pymacros/cells/draw_diode.py @@ -363,10 +363,9 @@ def draw_diode_nd2ps( c.write_gds("diode_nd2ps_temp.gds") layout.read("diode_nd2ps_temp.gds") - cell_name = "diode_nd2ps_dev" os.remove("diode_nd2ps_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_diode_pd2nw( @@ -697,10 +696,9 @@ def draw_diode_pd2nw( c.write_gds("diode_pd2nw_temp.gds") layout.read("diode_pd2nw_temp.gds") - cell_name = "diode_pd2nw_dev" os.remove("diode_pd2nw_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_diode_nw2ps( @@ -838,10 +836,9 @@ def draw_diode_nw2ps( c.write_gds("diode_nw2ps_temp.gds") layout.read("diode_nw2ps_temp.gds") - cell_name = "diode_nw2ps_dev" os.remove("diode_nw2ps_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_diode_pw2dw( @@ -1275,10 +1272,9 @@ def draw_diode_pw2dw( c.write_gds("diode_pw2dw_temp.gds") layout.read("diode_pw2dw_temp.gds") - cell_name = "diode_pw2dw_dev" os.remove("diode_pw2dw_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_diode_dw2ps( @@ -1677,10 +1673,9 @@ def draw_diode_dw2ps( c.write_gds("diode_dw2ps_temp.gds") layout.read("diode_dw2ps_temp.gds") - cell_name = "diode_dw2ps_dev" os.remove("diode_dw2ps_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_sc_diode( @@ -2073,7 +2068,6 @@ def sc_anode_strap(size: Float2 = (0.1, 0.1)) -> gf.Component: c.write_gds("sc_diode_temp.gds") layout.read("sc_diode_temp.gds") - cell_name = "sc_diode_dev" os.remove("sc_diode_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) diff --git a/cells/klayout/pymacros/cells/draw_fet.py b/cells/klayout/pymacros/cells/draw_fet.py index 255f1834..0ee52c50 100644 --- a/cells/klayout/pymacros/cells/draw_fet.py +++ b/cells/klayout/pymacros/cells/draw_fet.py @@ -1208,7 +1208,6 @@ def bulk_m1_check(bulk_con_area, m1_area, c_inst, bulk_con): bulk_m1.ymin = bulk_con.ymin - (bulk_m1.size[1] - bulk_con.size[1]) / 2 -# @gf.cell def draw_nfet( layout, l_gate: float = 0.28, @@ -1289,7 +1288,7 @@ def draw_nfet( sd_l = sd_l_con # gds components to store a single instance and the generated device - c = gf.Component("sky_nfet_dev") + c = gf.Component("nfet_dev") c_inst = gf.Component("dev_temp") @@ -1425,7 +1424,6 @@ def draw_nfet( y_range=(rect_pc.ymin, rect_pc.ymax), base_layer=layer["poly2"], metal_level=1, - li_enc_dir="H", ) c_pl_con = c_pc.add_ref(poly_con) @@ -1712,11 +1710,9 @@ def draw_nfet( # creating layout and cell in klayout c.write_gds("nfet_temp.gds") layout.read("nfet_temp.gds") - cell_name = "sky_nfet_dev" os.remove("nfet_temp.gds") - return layout.cell(cell_name) - # return c + return layout.cell(c.name) @gf.cell @@ -1823,7 +1819,6 @@ def pfet_deep_nwell( return c -# @gf.cell def draw_pfet( layout, l_gate: float = 0.28, @@ -1907,7 +1902,7 @@ def draw_pfet( sd_l = sd_l_con # gds components to store a single instance and the generated device - c = gf.Component("sky_pfet_dev") + c = gf.Component("pfet_dev") c_inst = gf.Component("dev_temp") @@ -2043,7 +2038,6 @@ def draw_pfet( y_range=(rect_pc.ymin, rect_pc.ymax), base_layer=layer["poly2"], metal_level=1, - li_enc_dir="H", ) c_pl_con = c_pc.add_ref(poly_con) @@ -2342,12 +2336,12 @@ def draw_pfet( # bulk guardring # creating layout and cell in klayout + c.write_gds("pfet_temp.gds") layout.read("pfet_temp.gds") - cell_name = "sky_pfet_dev" os.remove("pfet_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_nfet_06v0_nvt( @@ -2416,7 +2410,7 @@ def draw_nfet_06v0_nvt( sd_l = sd_l_con # gds components to store a single instance and the generated device - c = gf.Component("sky_nfet_nvt_dev") + c = gf.Component("nfet_nvt_dev") c_inst = gf.Component("dev_temp") @@ -2554,7 +2548,6 @@ def draw_nfet_06v0_nvt( y_range=(rect_pc.ymin, rect_pc.ymax), base_layer=layer["poly2"], metal_level=1, - li_enc_dir="H", ) c_pc.add_ref(poly_con) @@ -2977,11 +2970,6 @@ def draw_nfet_06v0_nvt( c.write_gds("nfet_nvt_temp.gds") layout.read("nfet_nvt_temp.gds") - cell_name = "sky_nfet_nvt_dev" os.remove("nfet_nvt_temp.gds") - return layout.cell(cell_name) - - -if __name__ == "__main__": - pass + return layout.cell(c.name) diff --git a/cells/klayout/pymacros/cells/draw_res.py b/cells/klayout/pymacros/cells/draw_res.py index 0b31229a..a966fb76 100644 --- a/cells/klayout/pymacros/cells/draw_res.py +++ b/cells/klayout/pymacros/cells/draw_res.py @@ -105,12 +105,12 @@ def draw_metal_res( ) # creating layout and cell in klayout + c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) @gf.cell @@ -476,10 +476,9 @@ def draw_nplus_res( c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_pplus_res( @@ -561,10 +560,9 @@ def draw_pplus_res( c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) @gf.cell @@ -770,10 +768,9 @@ def draw_npolyf_res( c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_ppolyf_res( @@ -846,10 +843,9 @@ def draw_ppolyf_res( c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_ppolyf_u_high_Rs_res( @@ -1060,10 +1056,9 @@ def draw_ppolyf_u_high_Rs_res( c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) def draw_well_res( @@ -1237,7 +1232,6 @@ def comp_related_gen(size: Float2 = (0.42, 0.42)) -> gf.Component: c.write_gds("res_temp.gds") layout.read("res_temp.gds") - cell_name = "res_dev" os.remove("res_temp.gds") - return layout.cell(cell_name) + return layout.cell(c.name) diff --git a/cells/klayout/pymacros/cells/fet.py b/cells/klayout/pymacros/cells/fet.py index 3a454a0a..b782a53d 100644 --- a/cells/klayout/pymacros/cells/fet.py +++ b/cells/klayout/pymacros/cells/fet.py @@ -164,7 +164,7 @@ def transformation_from_shape_impl(self): return pya.Trans(self.shape.bbox().center()) def produce_impl(self): - instance = draw_nfet( + nfet_instance = draw_nfet( layout=self.layout, l_gate=self.l_gate, w_gate=self.w_gate, @@ -187,7 +187,7 @@ def produce_impl(self): patt_lbl=self.patt_lbl, ) write_cells = pya.CellInstArray( - instance.cell_index(), + nfet_instance.cell_index(), pya.Trans(pya.Point(0, 0)), pya.Vector(0, 0), pya.Vector(0, 0), diff --git a/cells/klayout/pymacros/cells/via_generator.py b/cells/klayout/pymacros/cells/via_generator.py index e2d20ccd..75bbdb59 100644 --- a/cells/klayout/pymacros/cells/via_generator.py +++ b/cells/klayout/pymacros/cells/via_generator.py @@ -1,27 +1,47 @@ -# Copyright 2022 Skywater 130nm pdk development +# Copyright 2023 GlobalFoundries PDK Authors # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# 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. ######################################################################################################################## -# via Generator for skywater130 +# via Generator for GF180MCU ######################################################################################################################## - from math import ceil, floor import gdsfactory as gf from gdsfactory.typings import Float2, LayerSpec from .layers_def import layer +import os + + +def get_level_num(base_layer, base_layers, metal_level, metal_layers): + level_1 = -1 + level_2 = -1 + + if base_layer in base_layers: + level_1 = -1 + else: + for i in range(len(metal_layers)): + if base_layer == metal_layers[i]: + level_1 = i + + if metal_level in base_layers: + level_2 = -1 + else: + for i in range(len(metal_layers)): + if metal_level == metal_layers[i]: + level_2 = i + + return level_1, level_2 @gf.cell @@ -79,10 +99,8 @@ def via_generator( def via_stack( x_range: Float2 = (0, 1), y_range: Float2 = (0, 1), - base_layer: LayerSpec = layer["comp"], - slotted_licon: int = 0, metal_level: int = 1, - li_enc_dir="V", + base_layer: LayerSpec = layer["comp"], ) -> gf.Component: """ @@ -208,33 +226,12 @@ def via_stack( return c -def get_level_num(base_layer, base_layers, metal_level, metal_layers): - level_1 = -1 - level_2 = -1 - - if base_layer in base_layers: - level_1 = -1 - else: - for i in range(len(metal_layers)): - if base_layer == metal_layers[i]: - level_1 = i - - if metal_level in base_layers: - level_2 = -1 - else: - for i in range(len(metal_layers)): - if metal_level == metal_layers[i]: - level_2 = i - - return level_1, level_2 - - def draw_via_dev( layout, x_min: float = 0, - y_min: float = 1, - x_max: float = 0, - y_max: float = 1, + y_min: float = 0, + x_max: float = 2, + y_max: float = 2, metal_level: str = "M1", base_layer: str = "comp", ): @@ -261,7 +258,6 @@ def draw_via_dev( c = gf.Component("via_stack_dev") # vias dimensions - x_range = x_max - x_min y_range = y_max - y_min @@ -400,15 +396,6 @@ def draw_via_dev( c.write_gds("via_stack_temp.gds") layout.read("via_stack_temp.gds") - cell_name = "via_stack_dev" - print(type(layout.cell(cell_name))) - - return layout.cell(cell_name) - + os.remove("via_stack_temp.gds") -# testing the generated methods -if __name__ == "__main__": - c = via_stack() - c.show() - # c = vias_gen_draw(base_layer="li",end_layer="poly") - # c.show() + return layout.cell(c.name) diff --git a/cells/klayout/pymacros/cells/vias_gen.py b/cells/klayout/pymacros/cells/vias_gen.py index 7cad9a91..c8975302 100644 --- a/cells/klayout/pymacros/cells/vias_gen.py +++ b/cells/klayout/pymacros/cells/vias_gen.py @@ -17,7 +17,6 @@ ######################################################################################################################## import pya -import os from .via_generator import draw_via_dev via_size = 0.26 @@ -56,10 +55,8 @@ def __init__(self): self.Type_handle.add_choice("M5", "M5") self.Type_handle.add_choice("Mtop", "Mtop") - self.param("x_min", self.TypeDouble, "X_min", default=0, unit="um") - self.param("y_min", self.TypeDouble, "Y_min", default=0, unit="um") - self.param("x_max", self.TypeDouble, "X_max", default=1, unit="um") - self.param("y_max", self.TypeDouble, "Y_max", default=1, unit="um") + self.param("x_max", self.TypeDouble, "width", default=1, unit="um") + self.param("y_max", self.TypeDouble, "length", default=1, unit="um") def display_text_impl(self): # Provide a descriptive text for the cell @@ -70,18 +67,18 @@ def coerce_parameters_impl(self): # We also update the numerical value or the shape, depending on which on has not changed. if self.metal_level == "Mtop": - if (self.x_max - self.x_min) < mt_min: - self.x_max = self.x_min + mt_min + if self.x_max < mt_min: + self.x_max = mt_min - if (self.y_max - self.y_min) < mt_min: - self.y_max = self.y_min + mt_min + if self.y_max < mt_min: + self.y_max = mt_min else: - if (self.x_max - self.x_min) < (via_size + (2 * via_enc)): - self.x_max = self.x_min + (via_size + (2 * via_enc)) + if self.x_max < (via_size + (2 * via_enc)): + self.x_max = (via_size + (2 * via_enc)) - if (self.y_max - self.y_min) < (via_size + (2 * via_enc)): - self.y_max = self.y_min + (via_size + (2 * via_enc)) + if self.y_max < (via_size + (2 * via_enc)): + self.y_max = (via_size + (2 * via_enc)) def can_create_from_shape_impl(self): # Implement the "Create PCell from shape" protocol: we can use any shape which @@ -90,8 +87,8 @@ def can_create_from_shape_impl(self): 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.r = self.shape.bbox().width() * self.layout.dbu / 2 + # bounding box x_max and layer + self.r = self.shape.bbox().x_max() * self.layout.dbu / 2 self.lc = self.layout.get_info(self.layer) def transformation_from_shape_impl(self): @@ -100,18 +97,17 @@ def transformation_from_shape_impl(self): return pya.Trans(self.shape.bbox().center()) def produce_impl(self): - np_instance = draw_via_dev( + + via_instance = draw_via_dev( self.layout, - x_min=self.x_min, - y_min=self.y_min, x_max=self.x_max, y_max=self.y_max, metal_level=self.metal_level, base_layer=self.base_layer, ) - print(type(np_instance)) + write_cells = pya.CellInstArray( - np_instance.cell_index(), + via_instance.cell_index(), pya.Trans(pya.Point(0, 0)), pya.Vector(0, 0), pya.Vector(0, 0),