From 4ff85e154929f0b2b22888d9489c755ae1c9419f Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Wed, 24 Aug 2022 15:08:23 +0200 Subject: [PATCH 01/10] nmos with contacts --- sky130/device_generators/nmos.py | 101 +++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 sky130/device_generators/nmos.py diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py new file mode 100644 index 000000000..6decc91fd --- /dev/null +++ b/sky130/device_generators/nmos.py @@ -0,0 +1,101 @@ +from math import ceil, floor +import gdsfactory as gf +import numpy as np +from gdsfactory.types import Float2, LayerSpec + +@gf.cell +def nmos( + diffusion_layer: LayerSpec = (65, 20), + poly_layer: LayerSpec = (66, 22), + gate_width: float = 0.42, + gate_length: float = 0.15, + sd_width: float = 0.3, + end_cap: float = 0.13, + contact_size: Float2 = (0.17, 0.17), + contact_spacing: Float2 = (0.17, 0.17), + contact_layer: LayerSpec = (66, 44), + contact_enclosure: float = (0.04,0.06) +) -> gf.Component: + + """Return NMOS. + + Args: + diffusion_layer: spec. + poly_layer: spec. + gate_width: for poly. + gate_length: for poly. + sd_width: source drain length. + end_cap : end cap length. + + + .. code:: + _______ + | poly | + _________| |_________ _ + | sd_width| | sd_width| | + |<------->| |<------->| |gate_width + |_________| |_________| | + | Lg | + |<---->| + |______| + + """ + c = gf.Component() + + + w_p = end_cap + gate_width + end_cap # poly total width + rect_p = gf.components.rectangle(size = (gate_length,w_p), layer= poly_layer) + poly = c.add_ref(rect_p) + + + l_d = sd_width + gate_length + sd_width # n diffution total length + rect_d = gf.components.rectangle(size = (l_d,gate_width), layer= diffusion_layer) + diff_n= c.add_ref(rect_d) + + poly.movex(sd_width) + poly.movey(-end_cap) + + + rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + + + nr = floor (gate_width / (2* contact_size[1])) + nc = floor (sd_width / (2* contact_size[0])) + + con_sp = list(contact_spacing) + con_sp[0] = con_sp[1] = contact_spacing[0] + contact_size[0] + + cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + + cont_arr1.move(contact_enclosure) + cont_arr2.movex(l_d- cont_arr2.xmax + cont_arr2.xmin- contact_size[0] - contact_enclosure[0]) + cont_arr2.movey(contact_enclosure[1]) + + + + if (gate_length <= contact_size[0]) : + pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[1] + cont_p = c.add_ref(rect_c) + cont_p.connect("e2", destination= poly.ports["e2"]) + cont_p.movey(contact_enclosure[1]) + else : + pc_x = gate_length + nc_p = floor (pc_x / (2* contact_size[0])) +1 + cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr3.movex(sd_width + contact_enclosure[0] ) + cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + + + pc_size = (pc_x, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact + rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + pc = c.add_ref(rect_pc) + pc.connect("e2", destination= poly.ports["e2"]) + + return c + + +if __name__ == "__main__": + #c = nmos(gate_length= 2, gate_width=10) # , sd_width= 5) + c = nmos() + c.show() From 486e5079db42ba1c9c003724cf712f8742407167 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Wed, 24 Aug 2022 19:50:30 +0200 Subject: [PATCH 02/10] generate nmos --- sky130/device_generators/nmos.py | 89 +++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 19 deletions(-) diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index 6decc91fd..977271439 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -14,7 +14,15 @@ def nmos( contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), contact_layer: LayerSpec = (66, 44), - contact_enclosure: float = (0.04,0.06) + contact_enclosure: float = (0.04,0.06), + diff_spacing : float = 0.27 , + diff_enclosure : Float2 = (0.18,0.18) , + diffp_layer : LayerSpec = (65,21) , + pwell_layer : LayerSpec = (64,20), + dnwell_enclosure: float = (0.4,0.4), + dnwell_layer : LayerSpec = (63,21) , + nf : int = 1 + ) -> gf.Component: """Return NMOS. @@ -42,20 +50,23 @@ def nmos( """ c = gf.Component() - + # generating poly and n+ diffusion w_p = end_cap + gate_width + end_cap # poly total width rect_p = gf.components.rectangle(size = (gate_length,w_p), layer= poly_layer) - poly = c.add_ref(rect_p) + # adding fingers + #poly = c.add_ref(rect_p) + poly = c.add_array(rect_p, rows= 1 , columns= nf , spacing= [sd_width+gate_length, 0 ]) - l_d = sd_width + gate_length + sd_width # n diffution total length + + l_d = (nf + 1)*(sd_width + gate_length ) - gate_length # n diffution total length rect_d = gf.components.rectangle(size = (l_d,gate_width), layer= diffusion_layer) diff_n= c.add_ref(rect_d) poly.movex(sd_width) poly.movey(-end_cap) - + # generating contacts of poly and n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -65,37 +76,77 @@ def nmos( con_sp = list(contact_spacing) con_sp[0] = con_sp[1] = contact_spacing[0] + contact_size[0] + min_gate_len , min_gate_wid , sd_width_min = 0.15 , 0.42 , 0.3 + cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) - cont_arr1.move(contact_enclosure) - cont_arr2.movex(l_d- cont_arr2.xmax + cont_arr2.xmin- contact_size[0] - contact_enclosure[0]) - cont_arr2.movey(contact_enclosure[1]) + cont_arr1.movex((sd_width_min-contact_size[0])/2) + cont_arr1.movey((min_gate_wid - contact_size[1])/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width_min- contact_size[0])/2)) + cont_arr2.movey((min_gate_wid - contact_size[1])/2) + - if (gate_length <= contact_size[0]) : - pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[1] - cont_p = c.add_ref(rect_c) - cont_p.connect("e2", destination= poly.ports["e2"]) - cont_p.movey(contact_enclosure[1]) + pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[0] + cont_p = c.add_array(rect_c, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + cont_p.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + cont_p.movey(gate_width + end_cap + contact_enclosure[1] ) + cont_p2 = c.add_array(rect_c, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + cont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + cont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) + else : pc_x = gate_length nc_p = floor (pc_x / (2* contact_size[0])) +1 - cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) - cont_arr3.movex(sd_width + contact_enclosure[0] ) - cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + for i in range(nf): + cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr3.movex(sd_width + contact_enclosure[0] + (i* (gate_length + sd_width)) ) + cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr5.movex(sd_width + contact_enclosure[0]+ (i* (gate_length + sd_width)) ) + cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) pc_size = (pc_x, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) - pc = c.add_ref(rect_pc) - pc.connect("e2", destination= poly.ports["e2"]) + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_u.movex(sd_width- ((pc_x - gate_length)/2)) + pc_u.movey(gate_width + end_cap) + + pc_d = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_d.movex(sd_width- ((pc_x - gate_length)/2)) + pc_d.movey(-pc_size[1]- end_cap) + + + + # generaing p+ bulk tie and its contact + rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) + diff_p = c.add_ref(rect_dp) + diff_p.connect("e1",destination= diff_n.ports["e3"]) + diff_p.movex(diff_spacing) + + cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr4.movex(l_d + diff_spacing + ((sd_width_min - contact_size[0])/2)) + cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + # generating pwell + rect_pw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= pwell_layer) + pwell = c.add_ref(rect_pw) + pwell.movex(-diff_enclosure[0]) + pwell.movey(-diff_enclosure[1]) + + # generating deep nwell + rect_dnw = gf.components.rectangle(size = (rect_pw.xmax - rect_pw.xmin + 2*dnwell_enclosure[0] , rect_pw.ymax - rect_pw.ymin + 2*dnwell_enclosure[1]), layer= dnwell_layer) + dnwell = c.add_ref(rect_dnw) + dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) + dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) return c if __name__ == "__main__": - #c = nmos(gate_length= 2, gate_width=10) # , sd_width= 5) + #c = nmos(gate_length= 2, gate_width=10) c = nmos() c.show() From ef60a25c82d383a05608b9b58c17472b539509f6 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Thu, 25 Aug 2022 11:23:11 +0200 Subject: [PATCH 03/10] adding pmos --- sky130/device_generators/nmos.py | 14 ++- sky130/device_generators/pmos.py | 164 +++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 sky130/device_generators/pmos.py diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index 977271439..d37a25a80 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -6,7 +6,7 @@ @gf.cell def nmos( diffusion_layer: LayerSpec = (65, 20), - poly_layer: LayerSpec = (66, 22), + poly_layer: LayerSpec = (66, 20), gate_width: float = 0.42, gate_length: float = 0.15, sd_width: float = 0.3, @@ -17,10 +17,10 @@ def nmos( contact_enclosure: float = (0.04,0.06), diff_spacing : float = 0.27 , diff_enclosure : Float2 = (0.18,0.18) , - diffp_layer : LayerSpec = (65,21) , + diffp_layer : LayerSpec = (65,44) , pwell_layer : LayerSpec = (64,20), dnwell_enclosure: float = (0.4,0.4), - dnwell_layer : LayerSpec = (63,21) , + dnwell_layer : LayerSpec = (64,18) , nf : int = 1 ) -> gf.Component: @@ -34,6 +34,14 @@ def nmos( gate_length: for poly. sd_width: source drain length. end_cap : end cap length. + contact_size : contact dimension (length and width) + contact_layer : for contacts + contact_enclosure : for contacts within diffusion or poly + diff_spacing : for two adjacent diffusions + diff_enclosure : for diffusion within well + diffp_layer : for bulk tie + dnwell layer : for deep nwell + nf : for finger option .. code:: diff --git a/sky130/device_generators/pmos.py b/sky130/device_generators/pmos.py new file mode 100644 index 000000000..710a0a010 --- /dev/null +++ b/sky130/device_generators/pmos.py @@ -0,0 +1,164 @@ +from math import ceil, floor +import gdsfactory as gf +import numpy as np +from gdsfactory.types import Float2, LayerSpec + +@gf.cell +def pmos( + diffusion_layer: LayerSpec = (65, 20), + poly_layer: LayerSpec = (66, 20), + gate_width: float = 0.42, + gate_length: float = 0.15, + sd_width: float = 0.3, + end_cap: float = 0.13, + contact_size: Float2 = (0.17, 0.17), + contact_spacing: Float2 = (0.17, 0.17), + contact_layer: LayerSpec = (66, 44), + contact_enclosure: float = (0.04,0.06), + diff_spacing : float = 0.27 , + diff_enclosure : Float2 = (0.18,0.18) , + diffn_layer : LayerSpec = (65,44) , + nwell_layer : LayerSpec = (64,20), + dnwell_enclosure: float = (0.4,0.4), + dnwell_layer : LayerSpec = (64,18) , + nf : int = 1 + +) -> gf.Component: + + """Return PMOS. + + Args: + diffusion_layer: spec. + poly_layer: spec. + gate_width: for poly. + gate_length: for poly. + sd_width: source drain length. + end_cap : end cap length. + contact_size : contact dimension (length and width) + contact_layer : for contacts + contact_enclosure : for contacts within diffusion or poly + diff_spacing : for two adjacent diffusions + diff_enclosure : for diffusion within well + diffn_layer : for bulk tie + dnwell layer : for deep nwell + + + .. code:: + _______ + | poly | + _________| |_________ _ + | sd_width| | sd_width| | + |<------->| |<------->| |gate_width + |_________| |_________| | + | Lg | + |<---->| + |______| + + """ + + c = gf.Component() + + # generating poly and n+ diffusion + w_p = end_cap + gate_width + end_cap # poly total width + rect_p = gf.components.rectangle(size = (gate_length,w_p), layer= poly_layer) + + # adding fingers + #poly = c.add_ref(rect_p) + poly = c.add_array(rect_p, rows= 1 , columns= nf , spacing= [sd_width+gate_length, 0 ]) + + + l_d = (nf + 1)*(sd_width + gate_length ) - gate_length # n diffution total length + rect_d = gf.components.rectangle(size = (l_d,gate_width), layer= diffusion_layer) + diff_p= c.add_ref(rect_d) + + poly.movex(sd_width) + poly.movey(-end_cap) + + # generating contacts of poly and n+ diffusion + rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + + + nr = floor (gate_width / (2* contact_size[1])) + nc = floor (sd_width / (2* contact_size[0])) + + con_sp = list(contact_spacing) + con_sp[0] = con_sp[1] = contact_spacing[0] + contact_size[0] + + min_gate_len , min_gate_wid , sd_width_min = 0.15 , 0.42 , 0.3 + + cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + + cont_arr1.movex((sd_width_min-contact_size[0])/2) + cont_arr1.movey((min_gate_wid - contact_size[1])/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width_min- contact_size[0])/2)) + cont_arr2.movey((min_gate_wid - contact_size[1])/2) + + + + if (gate_length <= contact_size[0]) : + pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[0] + cont_p = c.add_array(rect_c, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + cont_p.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + cont_p.movey(gate_width + end_cap + contact_enclosure[1] ) + cont_p2 = c.add_array(rect_c, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + cont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + cont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) + + else : + pc_x = gate_length + nc_p = floor (pc_x / (2* contact_size[0])) +1 + for i in range(nf): + cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr3.movex(sd_width + contact_enclosure[0] + (i* (gate_length + sd_width)) ) + cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr5.movex(sd_width + contact_enclosure[0]+ (i* (gate_length + sd_width)) ) + cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + + + pc_size = (pc_x, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact + rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_u.movex(sd_width- ((pc_x - gate_length)/2)) + pc_u.movey(gate_width + end_cap) + + pc_d = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_d.movex(sd_width- ((pc_x - gate_length)/2)) + pc_d.movey(-pc_size[1]- end_cap) + + + # generaing n+ bulk tie and its contact + rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) + diff_n = c.add_ref(rect_dn) + diff_n.connect("e1",destination= diff_p.ports["e3"]) + diff_n.movex(diff_spacing) + + cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr4.movex(l_d + diff_spacing + ((sd_width_min - contact_size[0])/2)) + cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + # generating nwell + rect_nw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= nwell_layer) + nwell = c.add_ref(rect_nw) + nwell.movex(-diff_enclosure[0]) + nwell.movey(-diff_enclosure[1]) + + # generating deep nwell + rect_dnw = gf.components.rectangle(size = (rect_nw.xmax - rect_nw.xmin + 2*dnwell_enclosure[0] , rect_nw.ymax - rect_nw.ymin + 2*dnwell_enclosure[1]), layer= dnwell_layer) + dnwell = c.add_ref(rect_dnw) + dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) + dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) + + + + + return c + + +if __name__ == "__main__": + #c = pmos(gate_length= 2, gate_width=5,sd_width= 5 ) + c = pmos() + c.show() + + From 342cfd0bcfd28708eef56ff404d9f827cad11a30 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Thu, 25 Aug 2022 14:10:40 +0200 Subject: [PATCH 04/10] adding n+ & p+ implants --- sky130/device_generators/nmos.py | 42 ++++++++++++++++++++++++++------ sky130/device_generators/pmos.py | 39 +++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index d37a25a80..c0f94acd1 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -18,10 +18,13 @@ def nmos( diff_spacing : float = 0.27 , diff_enclosure : Float2 = (0.18,0.18) , diffp_layer : LayerSpec = (65,44) , - pwell_layer : LayerSpec = (64,20), + pwell_layer : LayerSpec = (64,22), dnwell_enclosure: float = (0.4,0.4), dnwell_layer : LayerSpec = (64,18) , - nf : int = 1 + nf : int = 1 , + sdm_enclosure : Float2 = (0.125,0.125) , + nsdm_layer : LayerSpec = (93,44), + psdm_layer : LayerSpec = (94,20) ) -> gf.Component: @@ -74,6 +77,12 @@ def nmos( poly.movex(sd_width) poly.movey(-end_cap) + # generating n+ implant + rect_nm = gf.components.rectangle(size = (l_d+ 2*sdm_enclosure[0] ,gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) + nsdm = c.add_ref(rect_nm) + nsdm.movex(-sdm_enclosure[0]) + nsdm.movey(-sdm_enclosure[1]) + # generating contacts of poly and n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -89,10 +98,16 @@ def nmos( cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) - cont_arr1.movex((sd_width_min-contact_size[0])/2) cont_arr1.movey((min_gate_wid - contact_size[1])/2) - cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width_min- contact_size[0])/2)) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + + if nc > 1 : + cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + else : + cont_arr1.movex ((sd_width - contact_size[0])/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + @@ -110,10 +125,10 @@ def nmos( nc_p = floor (pc_x / (2* contact_size[0])) +1 for i in range(nf): cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) - cont_arr3.movex(sd_width + contact_enclosure[0] + (i* (gate_length + sd_width)) ) + cont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) - cont_arr5.movex(sd_width + contact_enclosure[0]+ (i* (gate_length + sd_width)) ) + cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) @@ -136,9 +151,20 @@ def nmos( diff_p.movex(diff_spacing) cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) - cont_arr4.movex(l_d + diff_spacing + ((sd_width_min - contact_size[0])/2)) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + if nc > 1 : + cont_arr4.movex(l_d + diff_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + else : + cont_arr4.movex(l_d + diff_spacing + ((sd_width - contact_size[0])/2)) + + # generating p+ implant for bulk tie + rect_pm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) + psdm = c.add_ref(rect_pm) + psdm.connect("e1",destination= diff_n.ports["e3"]) + psdm.movex(diff_spacing - sdm_enclosure[0]) + + # generating pwell rect_pw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= pwell_layer) pwell = c.add_ref(rect_pw) @@ -155,6 +181,6 @@ def nmos( if __name__ == "__main__": - #c = nmos(gate_length= 2, gate_width=10) + #c = nmos(gate_length= 2, gate_width=10, sd_width= 5, nf = 3) c = nmos() c.show() diff --git a/sky130/device_generators/pmos.py b/sky130/device_generators/pmos.py index 710a0a010..a0d2d8a8d 100644 --- a/sky130/device_generators/pmos.py +++ b/sky130/device_generators/pmos.py @@ -21,7 +21,10 @@ def pmos( nwell_layer : LayerSpec = (64,20), dnwell_enclosure: float = (0.4,0.4), dnwell_layer : LayerSpec = (64,18) , - nf : int = 1 + nf : int = 1 , + sdm_enclosure : Float2 = (0.125,0.125) , + nsdm_layer : LayerSpec = (93,44), + psdm_layer : LayerSpec = (94,20) ) -> gf.Component: @@ -74,6 +77,12 @@ def pmos( poly.movex(sd_width) poly.movey(-end_cap) + # generating p+ implant + rect_pm = gf.components.rectangle(size = (l_d+ 2*sdm_enclosure[0] ,gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) + psdm = c.add_ref(rect_pm) + psdm.movex(-sdm_enclosure[0]) + psdm.movey(-sdm_enclosure[1]) + # generating contacts of poly and n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -89,10 +98,16 @@ def pmos( cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) - cont_arr1.movex((sd_width_min-contact_size[0])/2) cont_arr1.movey((min_gate_wid - contact_size[1])/2) - cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width_min- contact_size[0])/2)) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + + if nc > 1 : + cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + else : + cont_arr1.movex ((sd_width - contact_size[0])/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + @@ -110,10 +125,10 @@ def pmos( nc_p = floor (pc_x / (2* contact_size[0])) +1 for i in range(nf): cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) - cont_arr3.movex(sd_width + contact_enclosure[0] + (i* (gate_length + sd_width)) ) + cont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) - cont_arr5.movex(sd_width + contact_enclosure[0]+ (i* (gate_length + sd_width)) ) + cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) @@ -135,9 +150,19 @@ def pmos( diff_n.movex(diff_spacing) cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) - cont_arr4.movex(l_d + diff_spacing + ((sd_width_min - contact_size[0])/2)) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + if nc > 1 : + cont_arr4.movex(l_d + diff_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + else : + cont_arr4.movex(l_d + diff_spacing + ((sd_width - contact_size[0])/2)) + + # generating n+ implant for bulk tie + rect_nm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) + nsdm = c.add_ref(rect_nm) + nsdm.connect("e1",destination= diff_p.ports["e3"]) + nsdm.movex(diff_spacing - sdm_enclosure[0]) + # generating nwell rect_nw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= nwell_layer) nwell = c.add_ref(rect_nw) @@ -157,7 +182,7 @@ def pmos( if __name__ == "__main__": - #c = pmos(gate_length= 2, gate_width=5,sd_width= 5 ) + #c = pmos(gate_length= 2, gate_width=5,nf = 3 ) c = pmos() c.show() From 680ff0b2f8490e1156d7f49a1b057888f1643bf6 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Thu, 25 Aug 2022 16:50:10 +0200 Subject: [PATCH 05/10] adding nmos/pmos 5v --- sky130/device_generators/nmos.py | 16 +-- sky130/device_generators/nmos_5v.py | 175 ++++++++++++++++++++++++++++ sky130/device_generators/pmos.py | 17 +-- sky130/device_generators/pmos_5v.py | 166 ++++++++++++++++++++++++++ 4 files changed, 359 insertions(+), 15 deletions(-) create mode 100644 sky130/device_generators/nmos_5v.py create mode 100644 sky130/device_generators/pmos_5v.py diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index c0f94acd1..497229425 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -24,6 +24,7 @@ def nmos( nf : int = 1 , sdm_enclosure : Float2 = (0.125,0.125) , nsdm_layer : LayerSpec = (93,44), + sdm_spacing : float = 0.13, psdm_layer : LayerSpec = (94,20) ) -> gf.Component: @@ -122,7 +123,7 @@ def nmos( else : pc_x = gate_length - nc_p = floor (pc_x / (2* contact_size[0])) +1 + nc_p = floor (pc_x / (2* contact_size[0])) for i in range(nf): cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) cont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) @@ -148,25 +149,25 @@ def nmos( rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) diff_p = c.add_ref(rect_dp) diff_p.connect("e1",destination= diff_n.ports["e3"]) - diff_p.movex(diff_spacing) + diff_p.movex(diff_spacing+ sdm_spacing) cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) if nc > 1 : - cont_arr4.movex(l_d + diff_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) else : - cont_arr4.movex(l_d + diff_spacing + ((sd_width - contact_size[0])/2)) + cont_arr4.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2)) # generating p+ implant for bulk tie rect_pm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) psdm = c.add_ref(rect_pm) psdm.connect("e1",destination= diff_n.ports["e3"]) - psdm.movex(diff_spacing - sdm_enclosure[0]) + psdm.movex(diff_spacing+ sdm_spacing - sdm_enclosure[0]) # generating pwell - rect_pw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= pwell_layer) + rect_pw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sdm_spacing+ sd_width , 2*diff_enclosure[1] + gate_width), layer= pwell_layer) pwell = c.add_ref(rect_pw) pwell.movex(-diff_enclosure[0]) pwell.movey(-diff_enclosure[1]) @@ -181,6 +182,7 @@ def nmos( if __name__ == "__main__": - #c = nmos(gate_length= 2, gate_width=10, sd_width= 5, nf = 3) + + #c = nmos(gate_length= 2, gate_width=10, nf = 3) c = nmos() c.show() diff --git a/sky130/device_generators/nmos_5v.py b/sky130/device_generators/nmos_5v.py new file mode 100644 index 000000000..bc9457568 --- /dev/null +++ b/sky130/device_generators/nmos_5v.py @@ -0,0 +1,175 @@ +from math import ceil, floor +import gdsfactory as gf +import numpy as np +from gdsfactory.types import Float2, LayerSpec + +@gf.cell +def nmos_5v( + diffusion_layer: LayerSpec = (65, 20), + poly_layer: LayerSpec = (66, 20), + gate_width: float = 0.75, + gate_length: float = 0.5, + sd_width: float = 0.3, + end_cap: float = 0.13, + contact_size: Float2 = (0.17, 0.17), + contact_spacing: Float2 = (0.17, 0.17), + contact_layer: LayerSpec = (66, 44), + contact_enclosure: float = (0.04,0.06), + diff_spacing : float = 0.37 , + diff_enclosure : Float2 = (0.33,0.33) , + diffp_layer : LayerSpec = (65,44) , + pwell_layer : LayerSpec = (64,22), + dnwell_enclosure: float = (0.4,0.4), + dnwell_layer : LayerSpec = (64,18) , + nf : int = 1 , + sdm_enclosure : Float2 = (0.125,0.125) , + nsdm_layer : LayerSpec = (93,44), + psdm_layer : LayerSpec = (94,20), + sdm_spacing : float = 0.13, + hvi_layer : LayerSpec= (75,20), + hvntm_layer : LayerSpec = (125,20), + hvntm_enclosure : Float2 = (0.185,0.185) + +) -> gf.Component: + """Return NMOS. + + Args: + diffusion_layer: spec. + poly_layer: spec. + gate_width: for poly. + gate_length: for poly. + sd_width: source drain length. + end_cap : end cap length. + contact_size : contact dimension (length and width) + contact_layer : for contacts + contact_enclosure : for contacts within diffusion or poly + diff_spacing : for two adjacent diffusions + diff_enclosure : for diffusion within well + diffp_layer : for bulk tie + dnwell layer : for deep nwell + nf : for finger option + """ + + c = gf.Component() + + # generating poly and n+ diffusion + w_p = end_cap + gate_width + end_cap # poly total width + rect_p = gf.components.rectangle(size = (gate_length,w_p), layer= poly_layer) + + # adding fingers + #poly = c.add_ref(rect_p) + poly = c.add_array(rect_p, rows= 1 , columns= nf , spacing= [sd_width+gate_length, 0 ]) + + + l_d = (nf + 1)*(sd_width + gate_length ) - gate_length # n diffution total length + rect_d = gf.components.rectangle(size = (l_d,gate_width), layer= diffusion_layer) + diff_n= c.add_ref(rect_d) + + poly.movex(sd_width) + poly.movey(-end_cap) + + # generating n+ implant + rect_nm = gf.components.rectangle(size = (l_d+ 2*sdm_enclosure[0] ,gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) + nsdm = c.add_ref(rect_nm) + nsdm.movex(-sdm_enclosure[0]) + nsdm.movey(-sdm_enclosure[1]) + + # generating contacts of poly and n+ diffusion + rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + + + nr = floor (gate_width / (2* contact_size[1])) + nc = floor (sd_width / (2* contact_size[0])) + + con_sp = list(contact_spacing) + con_sp[0] = con_sp[1] = contact_spacing[0] + contact_size[0] + + min_gate_len , min_gate_wid , sd_width_min = 0.15 , 0.42 , 0.3 + + cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + + cont_arr1.movey((min_gate_wid - contact_size[1])/2) + cont_arr2.movey((min_gate_wid - contact_size[1])/2) + + if nc > 1 : + cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + else : + cont_arr1.movex ((sd_width - contact_size[0])/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + + + + nc_p = floor (gate_length / (2* contact_size[0])) + for i in range(nf): + cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) + cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) + cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + + + pc_size = (gate_length, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact + rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_u.movex(sd_width- ((gate_length - gate_length)/2)) + pc_u.movey(gate_width + end_cap) + + pc_d = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_d.movex(sd_width) + pc_d.movey(-pc_size[1]- end_cap) + + # generaing p+ bulk tie and its contact + rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) + diff_p = c.add_ref(rect_dp) + diff_p.connect("e1",destination= diff_n.ports["e3"]) + diff_p.movex(diff_spacing+sdm_spacing) + + cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + if nc > 1 : + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + else : + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + + # generating p+ implant for bulk tie + rect_pm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) + psdm = c.add_ref(rect_pm) + psdm.connect("e1",destination= diff_n.ports["e3"]) + psdm.movex(diff_spacing + sdm_spacing - sdm_enclosure[0]) + + # generating pwell + rect_pw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sdm_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= pwell_layer) + pwell = c.add_ref(rect_pw) + pwell.movex(-diff_enclosure[0]) + pwell.movey(-diff_enclosure[1]) + + # generating deep nwell + rect_dnw = gf.components.rectangle(size = (rect_pw.xmax - rect_pw.xmin + 2*dnwell_enclosure[0] , rect_pw.ymax - rect_pw.ymin + 2*dnwell_enclosure[1]), layer= dnwell_layer) + dnwell = c.add_ref(rect_dnw) + dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) + dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) + + # generating hvi + rect_hv = gf.components.rectangle(size = (rect_pw.xmax - rect_pw.xmin + 2*dnwell_enclosure[0] , rect_pw.ymax - rect_pw.ymin + 2*dnwell_enclosure[1]), layer= hvi_layer) + dnwell = c.add_ref(rect_hv) + dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) + dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) + + + # generating hvntm for n+ implants + rect_hvn = gf.components.rectangle(size = (l_d+ 2*sdm_enclosure[0] + 2*hvntm_enclosure[0],gate_width+ 2*sdm_enclosure[1]+ 2*hvntm_enclosure[1]), layer= hvntm_layer) + hvntm = c.add_ref(rect_hvn) + hvntm.movex(-sdm_enclosure[0]- hvntm_enclosure[0]) + hvntm.movey(-sdm_enclosure[1]- hvntm_enclosure[1]) + + return c + +if __name__ == "__main__": + c = nmos_5v(gate_length= 2, gate_width=10, nf = 3) + c = nmos_5v() + c.show() + diff --git a/sky130/device_generators/pmos.py b/sky130/device_generators/pmos.py index a0d2d8a8d..f0278f294 100644 --- a/sky130/device_generators/pmos.py +++ b/sky130/device_generators/pmos.py @@ -24,6 +24,7 @@ def pmos( nf : int = 1 , sdm_enclosure : Float2 = (0.125,0.125) , nsdm_layer : LayerSpec = (93,44), + sdm_spacing : float = 0.13, psdm_layer : LayerSpec = (94,20) ) -> gf.Component: @@ -61,7 +62,7 @@ def pmos( c = gf.Component() - # generating poly and n+ diffusion + # generating poly and p+ diffusion w_p = end_cap + gate_width + end_cap # poly total width rect_p = gf.components.rectangle(size = (gate_length,w_p), layer= poly_layer) @@ -83,7 +84,7 @@ def pmos( psdm.movex(-sdm_enclosure[0]) psdm.movey(-sdm_enclosure[1]) - # generating contacts of poly and n+ diffusion + # generating contacts of poly and p+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -122,7 +123,7 @@ def pmos( else : pc_x = gate_length - nc_p = floor (pc_x / (2* contact_size[0])) +1 + nc_p = floor (pc_x / (2* contact_size[0])) for i in range(nf): cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) cont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) @@ -147,24 +148,24 @@ def pmos( rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) diff_n = c.add_ref(rect_dn) diff_n.connect("e1",destination= diff_p.ports["e3"]) - diff_n.movex(diff_spacing) + diff_n.movex(diff_spacing+ sdm_spacing) cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) if nc > 1 : - cont_arr4.movex(l_d + diff_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) else : - cont_arr4.movex(l_d + diff_spacing + ((sd_width - contact_size[0])/2)) + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) # generating n+ implant for bulk tie rect_nm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) nsdm = c.add_ref(rect_nm) nsdm.connect("e1",destination= diff_p.ports["e3"]) - nsdm.movex(diff_spacing - sdm_enclosure[0]) + nsdm.movex(diff_spacing + sdm_spacing - sdm_enclosure[0]) # generating nwell - rect_nw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= nwell_layer) + rect_nw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sdm_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= nwell_layer) nwell = c.add_ref(rect_nw) nwell.movex(-diff_enclosure[0]) nwell.movey(-diff_enclosure[1]) diff --git a/sky130/device_generators/pmos_5v.py b/sky130/device_generators/pmos_5v.py new file mode 100644 index 000000000..8b91a87f9 --- /dev/null +++ b/sky130/device_generators/pmos_5v.py @@ -0,0 +1,166 @@ +from math import ceil, floor +import gdsfactory as gf +import numpy as np +from gdsfactory.types import Float2, LayerSpec + +@gf.cell +def pmos_5v( + diffusion_layer: LayerSpec = (65, 20), + poly_layer: LayerSpec = (66, 20), + gate_width: float = 0.75, + gate_length: float = 0.5, + sd_width: float = 0.3, + end_cap: float = 0.13, + contact_size: Float2 = (0.17, 0.17), + contact_spacing: Float2 = (0.17, 0.17), + contact_layer: LayerSpec = (66, 44), + contact_enclosure: float = (0.04,0.06), + diff_spacing : float = 0.37 , + diff_enclosure : Float2 = (0.33,0.33) , + diffn_layer : LayerSpec = (65,44) , + nwell_layer : LayerSpec = (64,22), + dnwell_enclosure: float = (0.4,0.4), + dnwell_layer : LayerSpec = (64,18) , + nf : int = 1 , + sdm_enclosure : Float2 = (0.125,0.125) , + nsdm_layer : LayerSpec = (93,44), + psdm_layer : LayerSpec = (94,20), + sdm_spacing : float = 0.13, + hvi_layer : LayerSpec= (75,20) + +) -> gf.Component: + """Return NMOS. + + Args: + diffusion_layer: spec. + poly_layer: spec. + gate_width: for poly. + gate_length: for poly. + sd_width: source drain length. + end_cap : end cap length. + contact_size : contact dimension (length and width) + contact_layer : for contacts + contact_enclosure : for contacts within diffusion or poly + diff_spacing : for two adjacent diffusions + diff_enclosure : for diffusion within well + diffp_layer : for bulk tie + dnwell layer : for deep nwell + nf : for finger option + """ + + c = gf.Component() + + # generating poly and p+ diffusion + w_p = end_cap + gate_width + end_cap # poly total width + rect_p = gf.components.rectangle(size = (gate_length,w_p), layer= poly_layer) + + # adding fingers + #poly = c.add_ref(rect_p) + poly = c.add_array(rect_p, rows= 1 , columns= nf , spacing= [sd_width+gate_length, 0 ]) + + + l_d = (nf + 1)*(sd_width + gate_length ) - gate_length # n diffution total length + rect_d = gf.components.rectangle(size = (l_d,gate_width), layer= diffusion_layer) + diff_p= c.add_ref(rect_d) + + poly.movex(sd_width) + poly.movey(-end_cap) + + # generating p+ implant + rect_pm = gf.components.rectangle(size = (l_d+ 2*sdm_enclosure[0] ,gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) + psdm = c.add_ref(rect_pm) + psdm.movex(-sdm_enclosure[0]) + psdm.movey(-sdm_enclosure[1]) + + # generating contacts of poly and p+ diffusion + rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + + + nr = floor (gate_width / (2* contact_size[1])) + nc = floor (sd_width / (2* contact_size[0])) + + con_sp = list(contact_spacing) + con_sp[0] = con_sp[1] = contact_spacing[0] + contact_size[0] + + min_gate_len , min_gate_wid , sd_width_min = 0.15 , 0.42 , 0.3 + + cont_arr1 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr2 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + + cont_arr1.movey((min_gate_wid - contact_size[1])/2) + cont_arr2.movey((min_gate_wid - contact_size[1])/2) + + if nc > 1 : + cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + else : + cont_arr1.movex ((sd_width - contact_size[0])/2) + cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + + + + nc_p = floor (gate_length / (2* contact_size[0])) + for i in range(nf): + cont_arr3 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) + cont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) + cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) + cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + + + pc_size = (gate_length, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact + rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_u.movex(sd_width- ((gate_length - gate_length)/2)) + pc_u.movey(gate_width + end_cap) + + pc_d = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + pc_d.movex(sd_width) + pc_d.movey(-pc_size[1]- end_cap) + + + # generaing n+ bulk tie and its contact + rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) + diff_n = c.add_ref(rect_dn) + diff_n.connect("e1",destination= diff_p.ports["e3"]) + diff_n.movex(diff_spacing + sdm_spacing) + + cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) + cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + if nc > 1 : + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + else : + cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + + # generating n+ implant for bulk tie + rect_nm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) + nsdm = c.add_ref(rect_nm) + nsdm.connect("e1",destination= diff_p.ports["e3"]) + nsdm.movex(diff_spacing + sdm_spacing - sdm_enclosure[0]) + + # generating nwell + rect_nw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sdm_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= nwell_layer) + nwell = c.add_ref(rect_nw) + nwell.movex(-diff_enclosure[0]) + nwell.movey(-diff_enclosure[1]) + + # generating deep nwell + rect_dnw = gf.components.rectangle(size = (rect_nw.xmax - rect_nw.xmin + 2*dnwell_enclosure[0] , rect_nw.ymax - rect_nw.ymin + 2*dnwell_enclosure[1]), layer= dnwell_layer) + dnwell = c.add_ref(rect_dnw) + dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) + dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) + + # generating hvi + rect_hv = gf.components.rectangle(size = (rect_nw.xmax - rect_nw.xmin + 2*dnwell_enclosure[0] , rect_nw.ymax - rect_nw.ymin + 2*dnwell_enclosure[1]), layer= hvi_layer) + dnwell = c.add_ref(rect_hv) + dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) + dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) + + return c + +if __name__ == "__main__": + c = pmos_5v(gate_length= 2, gate_width=5,nf = 3 ) + #c = pmos_5v() + c.show() From a2dff83bc9c96a65839b2d685f82a0b4d4da4fe6 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Thu, 25 Aug 2022 18:32:56 +0200 Subject: [PATCH 06/10] adding local interconnects --- sky130/device_generators/nmos.py | 47 ++++++++++++++++++++++++++--- sky130/device_generators/nmos_5v.py | 46 +++++++++++++++++++++++++--- sky130/device_generators/pmos.py | 39 +++++++++++++++++++++--- sky130/device_generators/pmos_5v.py | 42 +++++++++++++++++++++++--- 4 files changed, 156 insertions(+), 18 deletions(-) diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index 497229425..66478cf47 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -25,8 +25,11 @@ def nmos( sdm_enclosure : Float2 = (0.125,0.125) , nsdm_layer : LayerSpec = (93,44), sdm_spacing : float = 0.13, - psdm_layer : LayerSpec = (94,20) - + psdm_layer : LayerSpec = (94,20), + li_width : float = 0.17 , + li_spacing : float = 0.17 , + li_layer : LayerSpec = (67,20), + li_enclosure : float = 0.08 ) -> gf.Component: """Return NMOS. @@ -84,7 +87,7 @@ def nmos( nsdm.movex(-sdm_enclosure[0]) nsdm.movey(-sdm_enclosure[1]) - # generating contacts of poly and n+ diffusion + # generating contacts and local interconnects of n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -102,15 +105,28 @@ def nmos( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) + li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) - + li1.movex ((sd_width - contact_size[0])/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + li1.movey(-li_enclosure/2) + li2.movey(-li_enclosure/2) + + # generating contacts and local interconnects of poly + if (gate_length <= contact_size[0]) : pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[0] @@ -120,6 +136,7 @@ def nmos( cont_p2 = c.add_array(rect_c, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) cont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) cont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) + else : pc_x = gate_length @@ -143,6 +160,15 @@ def nmos( pc_d.movex(sd_width- ((pc_x - gate_length)/2)) pc_d.movey(-pc_size[1]- end_cap) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) + lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_u.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) + lip_u.movey(gate_width + end_cap + contact_enclosure[1]) + + lip_d = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_d.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) + lip_d.movey(-pc_size[1]- end_cap + contact_enclosure[1]) + # generaing p+ bulk tie and its contact @@ -154,10 +180,21 @@ def nmos( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + # generate its local interconnects + li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + + if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + else : cont_arr4.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2)) + li4.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2)) + + li4.movey(-li_enclosure/2) + + # generating p+ implant for bulk tie rect_pm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) @@ -178,6 +215,8 @@ def nmos( dnwell.movex(-diff_enclosure[0]- dnwell_enclosure[0]) dnwell.movey(-diff_enclosure[1]- dnwell_enclosure[1]) + + return c diff --git a/sky130/device_generators/nmos_5v.py b/sky130/device_generators/nmos_5v.py index bc9457568..d59744e8d 100644 --- a/sky130/device_generators/nmos_5v.py +++ b/sky130/device_generators/nmos_5v.py @@ -28,7 +28,11 @@ def nmos_5v( sdm_spacing : float = 0.13, hvi_layer : LayerSpec= (75,20), hvntm_layer : LayerSpec = (125,20), - hvntm_enclosure : Float2 = (0.185,0.185) + hvntm_enclosure : Float2 = (0.185,0.185), + li_width : float = 0.17 , + li_spacing : float = 0.17 , + li_layer : LayerSpec = (67,20), + li_enclosure : float = 0.08 ) -> gf.Component: """Return NMOS. @@ -74,7 +78,7 @@ def nmos_5v( nsdm.movex(-sdm_enclosure[0]) nsdm.movey(-sdm_enclosure[1]) - # generating contacts of poly and n+ diffusion + # generating contacts and local interconnects of n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -92,14 +96,26 @@ def nmos_5v( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) + li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + li1.movex ((sd_width - contact_size[0])/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) - + li1.movey(-li_enclosure/2) + li2.movey(-li_enclosure/2) + + # generating contacts and local interconnects of poly nc_p = floor (gate_length / (2* contact_size[0])) for i in range(nf): @@ -114,13 +130,23 @@ def nmos_5v( pc_size = (gate_length, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) - pc_u.movex(sd_width- ((gate_length - gate_length)/2)) + pc_u.movex(sd_width) pc_u.movey(gate_width + end_cap) pc_d = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) pc_d.movex(sd_width) pc_d.movey(-pc_size[1]- end_cap) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) + lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_u.movex(sd_width - li_enclosure/2) + lip_u.movey(gate_width + end_cap + contact_enclosure[1] ) + + lip_d = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_d.movex(sd_width - li_enclosure/2) + lip_d.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + + # generaing p+ bulk tie and its contact rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) diff_p = c.add_ref(rect_dp) @@ -130,10 +156,18 @@ def nmos_5v( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + # generate its local interconnects + li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + + if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) else : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + + li4.movey(-li_enclosure/2) # generating p+ implant for bulk tie rect_pm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= psdm_layer) @@ -141,6 +175,8 @@ def nmos_5v( psdm.connect("e1",destination= diff_n.ports["e3"]) psdm.movex(diff_spacing + sdm_spacing - sdm_enclosure[0]) + + # generating pwell rect_pw = gf.components.rectangle(size = (2*diff_enclosure[0] + l_d + diff_spacing + sdm_spacing + sd_width , 2*diff_enclosure[1] + gate_width), layer= pwell_layer) pwell = c.add_ref(rect_pw) @@ -169,7 +205,7 @@ def nmos_5v( return c if __name__ == "__main__": - c = nmos_5v(gate_length= 2, gate_width=10, nf = 3) + #c = nmos_5v(gate_length= 2, gate_width=10) c = nmos_5v() c.show() diff --git a/sky130/device_generators/pmos.py b/sky130/device_generators/pmos.py index f0278f294..92ff7a731 100644 --- a/sky130/device_generators/pmos.py +++ b/sky130/device_generators/pmos.py @@ -25,7 +25,11 @@ def pmos( sdm_enclosure : Float2 = (0.125,0.125) , nsdm_layer : LayerSpec = (93,44), sdm_spacing : float = 0.13, - psdm_layer : LayerSpec = (94,20) + psdm_layer : LayerSpec = (94,20), + li_width : float = 0.17 , + li_spacing : float = 0.17 , + li_layer : LayerSpec = (67,20), + li_enclosure : float = 0.08 ) -> gf.Component: @@ -84,7 +88,7 @@ def pmos( psdm.movex(-sdm_enclosure[0]) psdm.movey(-sdm_enclosure[1]) - # generating contacts of poly and p+ diffusion + # generating contacts and local interconnect of p+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -102,15 +106,26 @@ def pmos( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) + li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + li1.movex ((sd_width - contact_size[0])/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + + li1.movey(-li_enclosure/2) + li2.movey(-li_enclosure/2) - + # generating contacts and local interconnects of poly if (gate_length <= contact_size[0]) : pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[0] @@ -143,6 +158,15 @@ def pmos( pc_d.movex(sd_width- ((pc_x - gate_length)/2)) pc_d.movey(-pc_size[1]- end_cap) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) + lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_u.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) + lip_u.movey(gate_width + end_cap + contact_enclosure[1]) + + lip_d = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_d.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) + lip_d.movey(-pc_size[1]- end_cap + contact_enclosure[1]) + # generaing n+ bulk tie and its contact rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) @@ -153,10 +177,17 @@ def pmos( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + # generate its local interconnects + li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) else : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + + li4.movey(-li_enclosure/2) # generating n+ implant for bulk tie rect_nm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) @@ -183,7 +214,7 @@ def pmos( if __name__ == "__main__": - #c = pmos(gate_length= 2, gate_width=5,nf = 3 ) + #c = pmos(gate_length= 2, gate_width=10,nf = 3) c = pmos() c.show() diff --git a/sky130/device_generators/pmos_5v.py b/sky130/device_generators/pmos_5v.py index 8b91a87f9..577cb5ec6 100644 --- a/sky130/device_generators/pmos_5v.py +++ b/sky130/device_generators/pmos_5v.py @@ -26,7 +26,11 @@ def pmos_5v( nsdm_layer : LayerSpec = (93,44), psdm_layer : LayerSpec = (94,20), sdm_spacing : float = 0.13, - hvi_layer : LayerSpec= (75,20) + hvi_layer : LayerSpec= (75,20), + li_width : float = 0.17 , + li_spacing : float = 0.17 , + li_layer : LayerSpec = (67,20), + li_enclosure : float = 0.08 ) -> gf.Component: """Return NMOS. @@ -72,7 +76,7 @@ def pmos_5v( psdm.movex(-sdm_enclosure[0]) psdm.movey(-sdm_enclosure[1]) - # generating contacts of poly and p+ diffusion + # generating contacts and interconnects of p+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) @@ -90,14 +94,26 @@ def pmos_5v( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) + li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + li1.movex ((sd_width - contact_size[0])/2) + li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) - + li1.movey(-li_enclosure/2) + li2.movey(-li_enclosure/2) + + + # generating contacts and local interconnects of poly nc_p = floor (gate_length / (2* contact_size[0])) for i in range(nf): @@ -119,6 +135,15 @@ def pmos_5v( pc_d.movex(sd_width) pc_d.movey(-pc_size[1]- end_cap) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) + lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_u.movex(sd_width - li_enclosure/2) + lip_u.movey(gate_width + end_cap + contact_enclosure[1] ) + + lip_d = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + lip_d.movex(sd_width - li_enclosure/2) + lip_d.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + # generaing n+ bulk tie and its contact rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) @@ -129,10 +154,17 @@ def pmos_5v( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + # generate its local interconnects + li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) else : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + + li4.movey(-li_enclosure/2) # generating n+ implant for bulk tie rect_nm = gf.components.rectangle(size = (sd_width+ 2*sdm_enclosure[0],gate_width+ 2*sdm_enclosure[1]), layer= nsdm_layer) @@ -161,6 +193,6 @@ def pmos_5v( return c if __name__ == "__main__": - c = pmos_5v(gate_length= 2, gate_width=5,nf = 3 ) - #c = pmos_5v() + #c = pmos_5v(gate_length= 2, gate_width=10,nf = 3 ) + c = pmos_5v() c.show() From 16c951373e403ea04e818730da260841d41c3705 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Sun, 28 Aug 2022 14:22:10 +0200 Subject: [PATCH 07/10] adding mcon and metal1 --- sky130/device_generators/nmos.py | 76 ++++++++++++++++++++++++++--- sky130/device_generators/nmos_5v.py | 68 +++++++++++++++++++++++--- sky130/device_generators/pmos.py | 72 ++++++++++++++++++++++++--- sky130/device_generators/pmos_5v.py | 67 ++++++++++++++++++++++--- 4 files changed, 256 insertions(+), 27 deletions(-) diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index 66478cf47..a87914de7 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -14,7 +14,7 @@ def nmos( contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), contact_layer: LayerSpec = (66, 44), - contact_enclosure: float = (0.04,0.06), + contact_enclosure: float = (0.06,0.06), diff_spacing : float = 0.27 , diff_enclosure : Float2 = (0.18,0.18) , diffp_layer : LayerSpec = (65,44) , @@ -29,7 +29,11 @@ def nmos( li_width : float = 0.17 , li_spacing : float = 0.17 , li_layer : LayerSpec = (67,20), - li_enclosure : float = 0.08 + li_enclosure : float = 0.08, + mcon_layer : LayerSpec = (67,44) , + mcon_enclosure : Float2 = (0.03,0.06), + m1_layer : LayerSpec = (68,20) + ) -> gf.Component: """Return NMOS. @@ -87,8 +91,9 @@ def nmos( nsdm.movex(-sdm_enclosure[0]) nsdm.movey(-sdm_enclosure[1]) - # generating contacts and local interconnects of n+ diffusion + # generating contacts and local interconnects and mcon and m1 of n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + rect_mc = gf.components.rectangle(size = contact_size, layer = mcon_layer) nr = floor (gate_width / (2* contact_size[1])) @@ -105,27 +110,49 @@ def nmos( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + mcont_arr1 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr2 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + + mcont_arr1.movey((min_gate_wid - contact_size[1])/2) + mcont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + #rect_m1d = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0], cont_arr1.ymax - cont_arr1.ymin + contact_size[1] + 2*mcon_enclosure[1]), layer= m1_layer) + rect_m1d = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1d1 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + m1d2 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + + + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + mcont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + m1d1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2) - mcon_enclosure[0]) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + mcont_arr1.movex ((sd_width - contact_size[0])/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) li1.movex ((sd_width - contact_size[0])/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + m1d1.movex ((sd_width - contact_size[0])/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) - mcon_enclosure[0] ) li1.movey(-li_enclosure/2) li2.movey(-li_enclosure/2) + - # generating contacts and local interconnects of poly + # generating contacts and local interconnects and mcon and m1 of poly if (gate_length <= contact_size[0]) : @@ -136,7 +163,14 @@ def nmos( cont_p2 = c.add_array(rect_c, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) cont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) cont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) - + + mcont_p = c.add_array(rect_mc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + mcont_p.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + mcont_p.movey(gate_width + end_cap + contact_enclosure[1] ) + mcont_p2 = c.add_array(rect_mc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + mcont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + mcont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) + else : pc_x = gate_length @@ -148,10 +182,18 @@ def nmos( cont_arr5 = c.add_array(rect_c, rows= 1 , columns= nc_p , spacing= con_sp) cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + mcont_arr3 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + mcont_arr5 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) pc_size = (pc_x, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + rect_m1p = gf.components.rectangle(size = (pc_x + 2*mcon_enclosure[0] - 2*contact_enclosure[0],contact_size[1]+2*mcon_enclosure[1]), layer = m1_layer) + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) pc_u.movex(sd_width- ((pc_x - gate_length)/2)) pc_u.movey(gate_width + end_cap) @@ -160,6 +202,14 @@ def nmos( pc_d.movex(sd_width- ((pc_x - gate_length)/2)) pc_d.movey(-pc_size[1]- end_cap) + m1p_u = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_u.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0] - mcon_enclosure[0]) + m1p_u.movey(gate_width + end_cap + contact_enclosure[1] - mcon_enclosure[1]) + + m1p_d = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_d.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0] - mcon_enclosure[0]) + m1p_d.movey(-pc_size[1]- end_cap + contact_enclosure[1] - contact_enclosure[1]) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) lip_u.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) @@ -171,7 +221,7 @@ def nmos( - # generaing p+ bulk tie and its contact + # generaing p+ bulk tie and its contact and mcon and m1 rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) diff_p = c.add_ref(rect_dp) diff_p.connect("e1",destination= diff_n.ports["e3"]) @@ -180,17 +230,29 @@ def nmos( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + mcont_arr4 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + rect_m1dp = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1dp = c.add_array(rect_m1dp, rows= 1 , columns= nc , spacing= con_sp) + + + # generate its local interconnects li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + m1dp.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2) - mcon_enclosure[0]) else : cont_arr4.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2)) + mcont_arr4.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2)) li4.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2)) + m1dp.movex(l_d + diff_spacing+ sdm_spacing + ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) li4.movey(-li_enclosure/2) @@ -222,6 +284,6 @@ def nmos( if __name__ == "__main__": - #c = nmos(gate_length= 2, gate_width=10, nf = 3) + #c = nmos(gate_length= 2, gate_width=1.2, nf =4) c = nmos() c.show() diff --git a/sky130/device_generators/nmos_5v.py b/sky130/device_generators/nmos_5v.py index d59744e8d..7f4844748 100644 --- a/sky130/device_generators/nmos_5v.py +++ b/sky130/device_generators/nmos_5v.py @@ -14,7 +14,7 @@ def nmos_5v( contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), contact_layer: LayerSpec = (66, 44), - contact_enclosure: float = (0.04,0.06), + contact_enclosure: float = (0.06,0.06), diff_spacing : float = 0.37 , diff_enclosure : Float2 = (0.33,0.33) , diffp_layer : LayerSpec = (65,44) , @@ -32,10 +32,15 @@ def nmos_5v( li_width : float = 0.17 , li_spacing : float = 0.17 , li_layer : LayerSpec = (67,20), - li_enclosure : float = 0.08 + li_enclosure : float = 0.08, + mcon_layer : LayerSpec = (67,44) , + mcon_enclosure : Float2 = (0.03,0.06), + m1_layer : LayerSpec = (68,20) + + ) -> gf.Component: - """Return NMOS. + """Return NMOS_5v. Args: diffusion_layer: spec. @@ -78,8 +83,9 @@ def nmos_5v( nsdm.movex(-sdm_enclosure[0]) nsdm.movey(-sdm_enclosure[1]) - # generating contacts and local interconnects of n+ diffusion + # generating contacts and local interconnects and mcon and m1 of n+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + rect_mc = gf.components.rectangle(size = contact_size, layer = mcon_layer) nr = floor (gate_width / (2* contact_size[1])) @@ -96,26 +102,44 @@ def nmos_5v( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + mcont_arr1 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr2 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + + mcont_arr1.movey((min_gate_wid - contact_size[1])/2) + mcont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + rect_m1d = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1d1 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + m1d2 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + mcont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + m1d1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2) - mcon_enclosure[0]) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + mcont_arr1.movex ((sd_width - contact_size[0])/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) li1.movex ((sd_width - contact_size[0])/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + m1d1.movex ((sd_width - contact_size[0])/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) li1.movey(-li_enclosure/2) li2.movey(-li_enclosure/2) - # generating contacts and local interconnects of poly + # generating contacts and local interconnects and mcon and m1 of poly nc_p = floor (gate_length / (2* contact_size[0])) for i in range(nf): @@ -126,9 +150,20 @@ def nmos_5v( cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + mcont_arr3 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + mcont_arr5 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + + pc_size = (gate_length, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + rect_m1p = gf.components.rectangle(size = (gate_length + 2*mcon_enclosure[0] - 2*contact_enclosure[0],contact_size[1]+2*mcon_enclosure[1]), layer = m1_layer) + + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) pc_u.movex(sd_width) pc_u.movey(gate_width + end_cap) @@ -137,6 +172,14 @@ def nmos_5v( pc_d.movex(sd_width) pc_d.movey(-pc_size[1]- end_cap) + m1p_u = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_u.movex(sd_width + contact_enclosure[0] - mcon_enclosure[0]) + m1p_u.movey(gate_width + end_cap + contact_enclosure[1] - mcon_enclosure[1]) + + m1p_d = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_d.movex(sd_width + contact_enclosure[0] - mcon_enclosure[0]) + m1p_d.movey(-pc_size[1]- end_cap + contact_enclosure[1] - contact_enclosure[1]) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) lip_u.movex(sd_width - li_enclosure/2) @@ -147,7 +190,7 @@ def nmos_5v( lip_d.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) - # generaing p+ bulk tie and its contact + # generaing p+ bulk tie and its contact and mcon and m1 rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) diff_p = c.add_ref(rect_dp) diff_p.connect("e1",destination= diff_n.ports["e3"]) @@ -156,16 +199,27 @@ def nmos_5v( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + mcont_arr4 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + rect_m1dp = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1dp = c.add_array(rect_m1dp, rows= 1 , columns= nc , spacing= con_sp) + + # generate its local interconnects li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + m1dp.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2) - mcon_enclosure[0]) else : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + m1dp.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) li4.movey(-li_enclosure/2) @@ -205,7 +259,7 @@ def nmos_5v( return c if __name__ == "__main__": - #c = nmos_5v(gate_length= 2, gate_width=10) + #c = nmos_5v(gate_length= 2, gate_width=5) c = nmos_5v() c.show() diff --git a/sky130/device_generators/pmos.py b/sky130/device_generators/pmos.py index 92ff7a731..a2123f397 100644 --- a/sky130/device_generators/pmos.py +++ b/sky130/device_generators/pmos.py @@ -14,7 +14,7 @@ def pmos( contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), contact_layer: LayerSpec = (66, 44), - contact_enclosure: float = (0.04,0.06), + contact_enclosure: float = (0.06,0.06), diff_spacing : float = 0.27 , diff_enclosure : Float2 = (0.18,0.18) , diffn_layer : LayerSpec = (65,44) , @@ -29,7 +29,11 @@ def pmos( li_width : float = 0.17 , li_spacing : float = 0.17 , li_layer : LayerSpec = (67,20), - li_enclosure : float = 0.08 + li_enclosure : float = 0.08, + mcon_layer : LayerSpec = (67,44) , + mcon_enclosure : Float2 = (0.03,0.06), + m1_layer : LayerSpec = (68,20) + ) -> gf.Component: @@ -88,8 +92,9 @@ def pmos( psdm.movex(-sdm_enclosure[0]) psdm.movey(-sdm_enclosure[1]) - # generating contacts and local interconnect of p+ diffusion + # generating contacts and local interconnect and mcon and m1 of p+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + rect_mc = gf.components.rectangle(size = contact_size, layer = mcon_layer) nr = floor (gate_width / (2* contact_size[1])) @@ -106,26 +111,46 @@ def pmos( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + mcont_arr1 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr2 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + + mcont_arr1.movey((min_gate_wid - contact_size[1])/2) + mcont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + rect_m1d = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1d1 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + m1d2 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + + + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + mcont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + m1d1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)- mcon_enclosure[0]) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + mcont_arr1.movex ((sd_width - contact_size[0])/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) li1.movex ((sd_width - contact_size[0])/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + m1d1.movex ((sd_width - contact_size[0])/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) li1.movey(-li_enclosure/2) li2.movey(-li_enclosure/2) - # generating contacts and local interconnects of poly + # generating contacts and local interconnects and mcon and m1 of poly if (gate_length <= contact_size[0]) : pc_x = contact_enclosure[0] +contact_size[0] + contact_enclosure[0] @@ -136,6 +161,13 @@ def pmos( cont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) cont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) + mcont_p = c.add_array(rect_mc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + mcont_p.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + mcont_p.movey(gate_width + end_cap + contact_enclosure[1] ) + mcont_p2 = c.add_array(rect_mc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + mcont_p2.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0]) + mcont_p2.movey(-end_cap - contact_enclosure[1] - contact_size[1]) + else : pc_x = gate_length nc_p = floor (pc_x / (2* contact_size[0])) @@ -147,9 +179,19 @@ def pmos( cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + mcont_arr3 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + mcont_arr5 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + pc_size = (pc_x, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + rect_m1p = gf.components.rectangle(size = (pc_x + 2*mcon_enclosure[0] - 2*contact_enclosure[0],contact_size[1]+2*mcon_enclosure[1]), layer = m1_layer) + + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) pc_u.movex(sd_width- ((pc_x - gate_length)/2)) pc_u.movey(gate_width + end_cap) @@ -158,6 +200,14 @@ def pmos( pc_d.movex(sd_width- ((pc_x - gate_length)/2)) pc_d.movey(-pc_size[1]- end_cap) + m1p_u = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_u.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0] - mcon_enclosure[0]) + m1p_u.movey(gate_width + end_cap + contact_enclosure[1] - mcon_enclosure[1]) + + m1p_d = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_d.movex(sd_width- ((pc_x - gate_length)/2) + contact_enclosure[0] - mcon_enclosure[0]) + m1p_d.movey(-pc_size[1]- end_cap + contact_enclosure[1] - contact_enclosure[1]) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) lip_u.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) @@ -168,7 +218,7 @@ def pmos( lip_d.movey(-pc_size[1]- end_cap + contact_enclosure[1]) - # generaing n+ bulk tie and its contact + # generaing n+ bulk tie and its contact and mcon and m1 rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) diff_n = c.add_ref(rect_dn) diff_n.connect("e1",destination= diff_p.ports["e3"]) @@ -177,15 +227,25 @@ def pmos( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + mcont_arr4 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + rect_m1dn = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1dn = c.add_array(rect_m1dn, rows= 1 , columns= nc , spacing= con_sp) + # generate its local interconnects li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + m1dn.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2) - mcon_enclosure[0]) else : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + m1dn.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) li4.movey(-li_enclosure/2) @@ -214,7 +274,7 @@ def pmos( if __name__ == "__main__": - #c = pmos(gate_length= 2, gate_width=10,nf = 3) + #c = pmos(gate_length= 2, gate_width=10, sd_width=5) c = pmos() c.show() diff --git a/sky130/device_generators/pmos_5v.py b/sky130/device_generators/pmos_5v.py index 577cb5ec6..5bee49dd2 100644 --- a/sky130/device_generators/pmos_5v.py +++ b/sky130/device_generators/pmos_5v.py @@ -14,7 +14,7 @@ def pmos_5v( contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), contact_layer: LayerSpec = (66, 44), - contact_enclosure: float = (0.04,0.06), + contact_enclosure: float = (0.06,0.06), diff_spacing : float = 0.37 , diff_enclosure : Float2 = (0.33,0.33) , diffn_layer : LayerSpec = (65,44) , @@ -30,10 +30,13 @@ def pmos_5v( li_width : float = 0.17 , li_spacing : float = 0.17 , li_layer : LayerSpec = (67,20), - li_enclosure : float = 0.08 + li_enclosure : float = 0.08 , + mcon_layer : LayerSpec = (67,44), + mcon_enclosure : Float2 = (0.03,0.06), + m1_layer : LayerSpec = (68,20) ) -> gf.Component: - """Return NMOS. + """Return PMOS_5v. Args: diffusion_layer: spec. @@ -76,8 +79,9 @@ def pmos_5v( psdm.movex(-sdm_enclosure[0]) psdm.movey(-sdm_enclosure[1]) - # generating contacts and interconnects of p+ diffusion + # generating contacts and interconnects and mcon and m1 of p+ diffusion rect_c = gf.components.rectangle(size = contact_size, layer = contact_layer) + rect_mc = gf.components.rectangle(size = contact_size, layer = mcon_layer) nr = floor (gate_width / (2* contact_size[1])) @@ -94,26 +98,47 @@ def pmos_5v( cont_arr1.movey((min_gate_wid - contact_size[1])/2) cont_arr2.movey((min_gate_wid - contact_size[1])/2) + mcont_arr1 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr2 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + + mcont_arr1.movey((min_gate_wid - contact_size[1])/2) + mcont_arr2.movey((min_gate_wid - contact_size[1])/2) + rect_lid = gf.components.rectangle(size= (li_width , gate_width+ li_enclosure), layer= li_layer) li1 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) li2 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) + rect_m1d = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1d1 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + m1d2 = c.add_array(rect_m1d, rows= 1 , columns= nc , spacing= con_sp) + + if nc > 1 : cont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + mcont_arr1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) li1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2)) + m1d1.movex ((sd_width - (cont_arr1.xmax - cont_arr1.xmin))/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - (cont_arr2.xmax - cont_arr2.xmin))/2) - mcon_enclosure[0]) else : cont_arr1.movex ((sd_width - contact_size[0])/2) cont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + mcont_arr1.movex ((sd_width - contact_size[0])/2) + mcont_arr2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) li1.movex ((sd_width - contact_size[0])/2) li2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) ) + m1d1.movex ((sd_width - contact_size[0])/2 - mcon_enclosure[0]) + m1d2.movex((nf*(sd_width+ gate_length) )+ ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) + + li1.movey(-li_enclosure/2) li2.movey(-li_enclosure/2) - # generating contacts and local interconnects of poly + # generating contacts and local interconnects and mcon of poly nc_p = floor (gate_length / (2* contact_size[0])) for i in range(nf): @@ -124,9 +149,19 @@ def pmos_5v( cont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) cont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + mcont_arr3 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr3.movex(sd_width + ((gate_length - (cont_arr3.xmax - cont_arr3.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr3.movey(gate_width + end_cap + contact_enclosure[1] ) + mcont_arr5 = c.add_array(rect_mc, rows= 1 , columns= nc_p , spacing= con_sp) + mcont_arr5.movex(sd_width + ((gate_length - (cont_arr5.xmax - cont_arr5.xmin))/2)+ (i* (gate_length + sd_width)) ) + mcont_arr5.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + pc_size = (gate_length, contact_enclosure[1] +contact_size[1]+contact_enclosure[1]) # poly size to contain contact rect_pc = gf.components.rectangle(size = pc_size, layer = poly_layer) + rect_m1p = gf.components.rectangle(size = (gate_length + 2*mcon_enclosure[0] - 2*contact_enclosure[0],contact_size[1]+2*mcon_enclosure[1]), layer = m1_layer) + + pc_u = c.add_array(rect_pc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) pc_u.movex(sd_width- ((gate_length - gate_length)/2)) pc_u.movey(gate_width + end_cap) @@ -135,6 +170,14 @@ def pmos_5v( pc_d.movex(sd_width) pc_d.movey(-pc_size[1]- end_cap) + m1p_u = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_u.movex(sd_width + contact_enclosure[0] - mcon_enclosure[0]) + m1p_u.movey(gate_width + end_cap + contact_enclosure[1] - mcon_enclosure[1]) + + m1p_d = c.add_array(rect_m1p, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + m1p_d.movex(sd_width + contact_enclosure[0] - mcon_enclosure[0]) + m1p_d.movey(-pc_size[1]- end_cap + contact_enclosure[1] - contact_enclosure[1]) + rect_lip = gf.components.rectangle(size = (pc_size[0]+ li_enclosure, li_width), layer = li_layer) lip_u = c.add_array(rect_lip, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) lip_u.movex(sd_width - li_enclosure/2) @@ -145,7 +188,7 @@ def pmos_5v( lip_d.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) - # generaing n+ bulk tie and its contact + # generaing n+ bulk tie and its contact and mcon and m1 rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) diff_n = c.add_ref(rect_dn) diff_n.connect("e1",destination= diff_p.ports["e3"]) @@ -154,15 +197,25 @@ def pmos_5v( cont_arr4 = c.add_array(rect_c, rows= nr , columns= nc , spacing= con_sp) cont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + mcont_arr4 = c.add_array(rect_mc, rows= nr , columns= nc , spacing= con_sp) + mcont_arr4.movey((min_gate_wid - contact_size[1])/2 ) + + rect_m1dn = gf.components.rectangle(size= ( contact_size[0] + 2*mcon_enclosure[0],gate_width), layer=m1_layer) + m1dn = c.add_array(rect_m1dn, rows= 1 , columns= nc , spacing= con_sp) + # generate its local interconnects li4 = c.add_array(rect_lid, rows= 1 , columns= nc , spacing= con_sp) if nc > 1 : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2)) + m1dn.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - (cont_arr4.xmax - cont_arr4.xmin))/2) - mcon_enclosure[0]) else : cont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + mcont_arr4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) li4.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2)) + m1dn.movex(l_d + diff_spacing + sdm_spacing + ((sd_width - contact_size[0])/2) - mcon_enclosure[0]) li4.movey(-li_enclosure/2) @@ -193,6 +246,6 @@ def pmos_5v( return c if __name__ == "__main__": - #c = pmos_5v(gate_length= 2, gate_width=10,nf = 3 ) + #c = pmos_5v(gate_length= 2, gate_width=10, sd_width=5 ) c = pmos_5v() c.show() From 8c735767307ee74c89cc47192c05b2cf95283c1f Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Sun, 28 Aug 2022 15:06:26 +0200 Subject: [PATCH 08/10] adding npc --- sky130/device_generators/nmos.py | 19 +++++++++++++++++-- sky130/device_generators/nmos_5v.py | 18 +++++++++++++++++- sky130/device_generators/pmos.py | 17 ++++++++++++++++- sky130/device_generators/pmos_5v.py | 17 ++++++++++++++++- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/sky130/device_generators/nmos.py b/sky130/device_generators/nmos.py index a87914de7..404db7ee0 100644 --- a/sky130/device_generators/nmos.py +++ b/sky130/device_generators/nmos.py @@ -32,7 +32,9 @@ def nmos( li_enclosure : float = 0.08, mcon_layer : LayerSpec = (67,44) , mcon_enclosure : Float2 = (0.03,0.06), - m1_layer : LayerSpec = (68,20) + m1_layer : LayerSpec = (68,20), + npc_layer : LayerSpec = (95,20), + npc_spacing : float = 0.09 ) -> gf.Component: @@ -219,6 +221,19 @@ def nmos( lip_d.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) lip_d.movey(-pc_size[1]- end_cap + contact_enclosure[1]) + # generating npc for poly contacts + + npc_en = end_cap - npc_spacing + rect_npc = gf.components.rectangle(size = (pc_size[0] + npc_en, pc_size[1] + npc_en), layer = npc_layer) + + npc_u = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_u.movex(sd_width- ((pc_x - gate_length)/2) - npc_en/2) + npc_u.movey(gate_width + npc_spacing + npc_en/2) + + npc_d = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_d.movex(sd_width- ((pc_x - gate_length)/2) - npc_en/2) + npc_d.movey(-pc_size[1] - npc_en - npc_spacing - npc_en/2) + # generaing p+ bulk tie and its contact and mcon and m1 @@ -284,6 +299,6 @@ def nmos( if __name__ == "__main__": - #c = nmos(gate_length= 2, gate_width=1.2, nf =4) + #c = nmos(gate_length= 2, gate_width=10) c = nmos() c.show() diff --git a/sky130/device_generators/nmos_5v.py b/sky130/device_generators/nmos_5v.py index 7f4844748..7c84a8baf 100644 --- a/sky130/device_generators/nmos_5v.py +++ b/sky130/device_generators/nmos_5v.py @@ -35,7 +35,9 @@ def nmos_5v( li_enclosure : float = 0.08, mcon_layer : LayerSpec = (67,44) , mcon_enclosure : Float2 = (0.03,0.06), - m1_layer : LayerSpec = (68,20) + m1_layer : LayerSpec = (68,20), + npc_layer : LayerSpec = (95,20), + npc_spacing : float = 0.09 @@ -189,6 +191,20 @@ def nmos_5v( lip_d.movex(sd_width - li_enclosure/2) lip_d.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + # generating npc for poly contacts + + npc_en = end_cap - npc_spacing + rect_npc = gf.components.rectangle(size = (pc_size[0] + npc_en, pc_size[1] + npc_en), layer = npc_layer) + + npc_u = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_u.movex(sd_width - npc_en/2) + npc_u.movey(gate_width + npc_spacing + npc_en/2) + + npc_d = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_d.movex(sd_width - npc_en/2) + npc_d.movey(-pc_size[1] - npc_en - npc_spacing - npc_en/2) + + # generaing p+ bulk tie and its contact and mcon and m1 rect_dp = gf.components.rectangle(size = (sd_width,gate_width), layer= diffp_layer) diff --git a/sky130/device_generators/pmos.py b/sky130/device_generators/pmos.py index a2123f397..cc24e8204 100644 --- a/sky130/device_generators/pmos.py +++ b/sky130/device_generators/pmos.py @@ -32,7 +32,9 @@ def pmos( li_enclosure : float = 0.08, mcon_layer : LayerSpec = (67,44) , mcon_enclosure : Float2 = (0.03,0.06), - m1_layer : LayerSpec = (68,20) + m1_layer : LayerSpec = (68,20), + npc_layer : LayerSpec = (95,20), + npc_spacing : float = 0.09 ) -> gf.Component: @@ -217,6 +219,19 @@ def pmos( lip_d.movex(sd_width- ((pc_x - gate_length)/2) - li_enclosure/2) lip_d.movey(-pc_size[1]- end_cap + contact_enclosure[1]) + # generating npc for poly contacts + + npc_en = end_cap - npc_spacing + rect_npc = gf.components.rectangle(size = (pc_size[0] + npc_en, pc_size[1] + npc_en), layer = npc_layer) + + npc_u = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_u.movex(sd_width- ((pc_x - gate_length)/2) - npc_en/2) + npc_u.movey(gate_width + npc_spacing + npc_en/2) + + npc_d = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_d.movex(sd_width- ((pc_x - gate_length)/2) - npc_en/2) + npc_d.movey(-pc_size[1] - npc_en - npc_spacing - npc_en/2) + # generaing n+ bulk tie and its contact and mcon and m1 rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) diff --git a/sky130/device_generators/pmos_5v.py b/sky130/device_generators/pmos_5v.py index 5bee49dd2..d1cdc48ad 100644 --- a/sky130/device_generators/pmos_5v.py +++ b/sky130/device_generators/pmos_5v.py @@ -33,7 +33,9 @@ def pmos_5v( li_enclosure : float = 0.08 , mcon_layer : LayerSpec = (67,44), mcon_enclosure : Float2 = (0.03,0.06), - m1_layer : LayerSpec = (68,20) + m1_layer : LayerSpec = (68,20) , + npc_layer : LayerSpec = (95,20), + npc_spacing : float = 0.09 ) -> gf.Component: """Return PMOS_5v. @@ -187,6 +189,19 @@ def pmos_5v( lip_d.movex(sd_width - li_enclosure/2) lip_d.movey(-contact_size[1] - end_cap - contact_enclosure[1] ) + # generating npc for poly contacts + + npc_en = end_cap - npc_spacing + rect_npc = gf.components.rectangle(size = (pc_size[0] + npc_en, pc_size[1] + npc_en), layer = npc_layer) + + npc_u = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_u.movex(sd_width - npc_en/2) + npc_u.movey(gate_width + npc_spacing + npc_en/2) + + npc_d = c.add_array(rect_npc, rows= 1 , columns= nf , spacing= [sd_width + gate_length, 0] ) + npc_d.movex(sd_width - npc_en/2) + npc_d.movey(-pc_size[1] - npc_en - npc_spacing - npc_en/2) + # generaing n+ bulk tie and its contact and mcon and m1 rect_dn = gf.components.rectangle(size = (sd_width,gate_width), layer= diffn_layer) From 7875ebc86c9d20f7e7e537de66759a61022c6470 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Sun, 28 Aug 2022 18:51:48 +0200 Subject: [PATCH 09/10] starting mimcap_1 --- sky130/device_generators/mimcap_1.py | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 sky130/device_generators/mimcap_1.py diff --git a/sky130/device_generators/mimcap_1.py b/sky130/device_generators/mimcap_1.py new file mode 100644 index 000000000..c5e5c229b --- /dev/null +++ b/sky130/device_generators/mimcap_1.py @@ -0,0 +1,72 @@ +from math import ceil, floor +import gdsfactory as gf +import numpy as np +from gdsfactory.types import Float2, LayerSpec + +@gf.cell +def mimcap_1( + m3_layer : LayerSpec = (70,20), + via3_size : float = (0.2,0.2), + via3_layer : LayerSpec = (70,44), + via3_enclosure : Float2 = (0.09,0.09), + via3_spacing : Float2 = (0.2,0.35), + m4_spacing : float = 0.3, + m4_length : float = 0.3, + m4_layer : LayerSpec = (71,20), + capm_length : float = 1, + capm_width : float = 1, + capm_layer : LayerSpec = (89,44), + capm_enclosure : float = 0.14 + + + + +) -> gf.Component: + + """Return mimcap_1 + + mim cap between metal 3 and 4 + + + """ + c = gf.Component() + + en = (0.02,0.05) # for enclosure + #generating m3 plate + m3_length = capm_enclosure + capm_length + m4_spacing - capm_enclosure + m4_length + en[0] + m3_width = 2*capm_enclosure + capm_width + en[1] + rect_m3 = gf.components.rectangle(size= (m3_length,m3_width) , layer= m3_layer) + m3 = c.add_ref(rect_m3) + + # generate m4 plates + + rect_m4_1 = gf.components.rectangle(size= (m4_length,m3_width- en[1] ), layer= m4_layer) + m4_1 = c.add_ref(rect_m4_1) + m4_1.movex (m3_length - m4_length - en[0]/2) + m4_1.movey (en[1]/2) + + rect_m4_2 = gf.components.rectangle(size= (capm_length - 2*capm_enclosure ,capm_width - 2*capm_enclosure ), layer= m4_layer) + m4_1 = c.add_ref(rect_m4_2) + m4_1.connect("e3", destination= m3.ports["e3"]) + m4_1.movex(- capm_length + 2*capm_enclosure - en[0]/2 - m4_length - m4_spacing) + + # generate capm + rect_capm = gf.components.rectangle(size= (capm_length,capm_width) , layer= capm_layer) + capm = c.add_ref(rect_capm) + capm.connect("e3", destination= m4_1.ports["e3"]) + capm.movex(capm_length - capm_enclosure) + + + # generat3 via3 + #rect_via3 = gf.components.rectangle(size= via3_size, layer= via3_layer) + #via3_arr1 = c.add_ref(rect_via3) + + + + return c + +if __name__ == "__main__": + + c = mimcap_1() + #c = mimcap_1 (capm_length= 5 , capm_width= 3, m4_length=1) + c.show() From ffa288cb8b2389d6e03fc555e3da13e252a0b843 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Mon, 29 Aug 2022 11:18:51 +0200 Subject: [PATCH 10/10] addding via3 to mimcap_1 --- sky130/device_generators/mimcap_1.py | 63 +++++++++++++++++----------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/sky130/device_generators/mimcap_1.py b/sky130/device_generators/mimcap_1.py index c5e5c229b..b4217f2a6 100644 --- a/sky130/device_generators/mimcap_1.py +++ b/sky130/device_generators/mimcap_1.py @@ -9,14 +9,15 @@ def mimcap_1( via3_size : float = (0.2,0.2), via3_layer : LayerSpec = (70,44), via3_enclosure : Float2 = (0.09,0.09), - via3_spacing : Float2 = (0.2,0.35), - m4_spacing : float = 0.3, - m4_length : float = 0.3, + via3_spacing : Float2 = (0.2,0.2),#(0.2,0.35), + m4_spacing : float = 0.4, + m4_r_length : float = 0.4, m4_layer : LayerSpec = (71,20), - capm_length : float = 1, - capm_width : float = 1, + m4_length : float = 1.2, + m4_width : float = 1.2, capm_layer : LayerSpec = (89,44), - capm_enclosure : float = 0.14 + m4_enclosure : float = (0.14,0.14), + capm_enclosure : float = (0.5,0.5) @@ -31,36 +32,50 @@ def mimcap_1( """ c = gf.Component() - en = (0.02,0.05) # for enclosure + en = (0.02,0.04) # for enclosure #generating m3 plate - m3_length = capm_enclosure + capm_length + m4_spacing - capm_enclosure + m4_length + en[0] - m3_width = 2*capm_enclosure + capm_width + en[1] + m3_length = capm_enclosure[0] + 2*m4_enclosure[0] + m4_length + m4_spacing + m4_r_length +en[0] + m3_width = 2*capm_enclosure[1] + 2*m4_enclosure[1] + m4_width + en[1] rect_m3 = gf.components.rectangle(size= (m3_length,m3_width) , layer= m3_layer) m3 = c.add_ref(rect_m3) # generate m4 plates - rect_m4_1 = gf.components.rectangle(size= (m4_length,m3_width- en[1] ), layer= m4_layer) - m4_1 = c.add_ref(rect_m4_1) - m4_1.movex (m3_length - m4_length - en[0]/2) - m4_1.movey (en[1]/2) + rect_m4_r = gf.components.rectangle(size= (m4_r_length,m3_width- en[1] ), layer= m4_layer) + m4_r = c.add_ref(rect_m4_r) + m4_r.movex (m3_length - m4_r_length- en[0]/2) + m4_r.movey (en[1]/2) - rect_m4_2 = gf.components.rectangle(size= (capm_length - 2*capm_enclosure ,capm_width - 2*capm_enclosure ), layer= m4_layer) - m4_1 = c.add_ref(rect_m4_2) - m4_1.connect("e3", destination= m3.ports["e3"]) - m4_1.movex(- capm_length + 2*capm_enclosure - en[0]/2 - m4_length - m4_spacing) + rect_m4_l = gf.components.rectangle(size= (m4_length,m4_width), layer= m4_layer) + m4_l = c.add_ref(rect_m4_l) + m4_l.connect("e3", destination= m3.ports["e1"]) + m4_l.movex(m4_length + capm_enclosure[0] + m4_enclosure[0] + en[0]/2 ) # generate capm - rect_capm = gf.components.rectangle(size= (capm_length,capm_width) , layer= capm_layer) + rect_capm = gf.components.rectangle(size= (m4_length + 2*m4_enclosure[0] ,m4_width + 2*m4_enclosure[1]) , layer= capm_layer) capm = c.add_ref(rect_capm) - capm.connect("e3", destination= m4_1.ports["e3"]) - capm.movex(capm_length - capm_enclosure) + capm.connect("e3", destination= m4_l.ports["e1"]) + capm.movex(m4_length + m4_enclosure[0]) # generat3 via3 - #rect_via3 = gf.components.rectangle(size= via3_size, layer= via3_layer) - #via3_arr1 = c.add_ref(rect_via3) - + rect_via3 = gf.components.rectangle(size= via3_size, layer= via3_layer) + + # for the left m4 plate + nc1 = floor ((m4_length) / (via3_size[0] + via3_spacing[0])) + nr1 = floor ((m4_width) / (via3_size[1] + via3_spacing[1])) + via3_arr1 = c.add_array(rect_via3 , rows= nr1 , columns= nc1 , spacing= (via3_spacing[0]+ via3_size[0], via3_spacing[1]+ via3_size[1])) + via3_arr1.movex (capm_enclosure[0] + m4_enclosure[0] + ((m4_length - nc1*via3_size[0] - (nc1-1)*via3_spacing[0])/2)) + via3_arr1.movey(capm_enclosure[1] + m4_enclosure[1] + ((m4_width - nr1*via3_size[1] - (nr1-1)*via3_spacing[1])/2 )) + + # for the right m4 plate + nr2 = floor ((m3_width - en[1]) / (via3_size[1]+ via3_spacing[1])) + nc2 = floor ((m4_r_length) / (via3_size[0]+via3_spacing[0])) + via3_arr2 = c.add_array(rect_via3 , rows= nr2 , columns= nc2 , spacing= (via3_spacing[0]+ via3_size[0], via3_spacing[1]+ via3_size[1])) + via3_arr2.movex(m3_length - en[0]/2 - m4_r_length) + via3_arr2.movex((m4_r_length - nc2*via3_size[0] - (nc2-1)*via3_spacing[0])/2) + via3_arr2.movey((m3_width - en[1]/2 - nr2*via3_size[1] - (nr2 - 1)*via3_spacing[1])/2 ) + return c @@ -68,5 +83,5 @@ def mimcap_1( if __name__ == "__main__": c = mimcap_1() - #c = mimcap_1 (capm_length= 5 , capm_width= 3, m4_length=1) + #c = mimcap_1 (m4_length=1.8, m4_width=1.8 , m4_r_length=0.5) c.show()