diff --git a/docs/_config.yml b/docs/_config.yml index 9775b42e2..28aedb08d 100755 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -31,7 +31,7 @@ html: # Information about where the book exists on the web repository: - url: https://github.com/gdsfactory/ubc + url: https://github.com/gdsfactory/skywater130 path_to_book: docs # Optional path to your book, relative to the repository root branch: main # Which branch of the repository should be used when creating links (optional) @@ -52,7 +52,7 @@ sphinx: autodoc_type_aliases: "ComponentSpec": "ComponentSpec" nb_execution_show_tb: True - nb_custom_formats: - .py: - - jupytext.reads - - fmt: py + # nb_custom_formats: + # .py: + # - jupytext.reads + # - fmt: py diff --git a/pyproject.toml b/pyproject.toml index 2412d99d7..221dad5cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ "Operating System :: OS Independent" ] dependencies = [ - "gdsfactory~=8.4.0", + "gdsfactory~=8.5.2", "PySpice" ] description = "skywater130 pdk" diff --git a/sky130/pcells/mimcap_2.py b/sky130/pcells/mimcap_2.py index 237d9a88b..460d97295 100644 --- a/sky130/pcells/mimcap_2.py +++ b/sky130/pcells/mimcap_2.py @@ -71,7 +71,9 @@ def mimcap_2( rect_m5_l = gf.components.rectangle(size=(m5_length, m5_width), layer=m5_layer) m5_l = c.add_ref(rect_m5_l) - m5_l.connect("e3", m4.ports["e1"], allow_layer_mismatch=True) + m5_l.connect( + "e3", m4.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) m5_l.dmovex(m5_length + capm2_enclosure[0] + m5_enclosure[0] + en[0] / 2) # generate capm2 @@ -80,7 +82,9 @@ def mimcap_2( layer=capm2_layer, ) capm2 = c.add_ref(rect_capm2) - capm2.connect("e3", m5_l.ports["e1"], allow_layer_mismatch=True) + capm2.connect( + "e3", m5_l.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) capm2.dmovex(m5_length + m5_enclosure[0]) # generat3 via4 diff --git a/sky130/pcells/nmos_5v.py b/sky130/pcells/nmos_5v.py index d26bd9625..d567d0f27 100644 --- a/sky130/pcells/nmos_5v.py +++ b/sky130/pcells/nmos_5v.py @@ -56,6 +56,22 @@ def nmos_5v( diffp_layer: for bulk tie. dnwell layer: for deep nwell. nf: for finger option. + sdm_enclosure: for n+ diffusion. + nsdm_layer: for n+ diffusion. + psdm_layer: for p+ diffusion. + sdm_spacing: for n+ diffusion. + hvi_layer: for high voltage implant. + hvntm_layer: for high voltage n+ implant. + hvntm_enclosure: for high voltage n+ implant. + li_width: for local interconnect. + li_layer: for local interconnect. + li_enclosure: for local interconnect. + mcon_layer: for metal contact. + mcon_enclosure: for metal contact. + m1_layer: for metal1. + npc_layer: for poly contact. + npc_spacing: for poly contact. + .. plot:: :include-source: diff --git a/sky130/pcells/npn_W1L1.py b/sky130/pcells/npn_W1L1.py index fc3ee240f..887c1ec92 100644 --- a/sky130/pcells/npn_W1L1.py +++ b/sky130/pcells/npn_W1L1.py @@ -34,6 +34,31 @@ def npn_W1L1( npn device with emitter size 1u*1u + Args: + E_width: width of the emitter. + E_length: length of the emitter. + B_width: width of the base. + C_width: width of the collector. + np_spacing: spacing between np regions. + diffusion_layer: layer of the diffusion. + tap_layer: layer of the tap. + diff_enclosure: enclosure of the diffusion. + contact_size: size of the contact. + contact_spacing: spacing between the contacts. + contact_layer: layer of the contact. + contact_enclosure: enclosure of the contact. + pwell_layer: layer of the pwell. + dnwell_layer: layer of the dnwell. + sdm_enclosure: enclosure of the sdm. + nsdm_layer: layer of the nsdm. + psdm_layer: layer of the psdm. + npn_layer: layer of the npn. + li_layer: layer of the li. + li_enclosure: enclosure of the li. + mcon_layer: layer of the mcon. + mcon_enclosure: enclosure of the mcon. + m1_layer: layer of the m1. + .. plot:: :include-source: diff --git a/sky130/pcells/npn_W1L2.py b/sky130/pcells/npn_W1L2.py index a6c206200..1fce61d96 100644 --- a/sky130/pcells/npn_W1L2.py +++ b/sky130/pcells/npn_W1L2.py @@ -19,15 +19,11 @@ def npn_W1L2( contact_layer: LayerSpec = (66, 44), contact_enclosure: Float2 = (0.06, 0.06), pwell_layer: LayerSpec = (64, 13), - dnwell_enclosure: Float2 = (0.4, 0.4), dnwell_layer: LayerSpec = (64, 18), sdm_enclosure: Float2 = (0.125, 0.125), nsdm_layer: LayerSpec = (93, 44), - sdm_spacing: float = 0.13, psdm_layer: LayerSpec = (94, 20), npn_layer: LayerSpec = (82, 20), - li_width: float = 0.17, - li_spacing: float = 0.17, li_layer: LayerSpec = (67, 20), li_enclosure: float = 0.08, mcon_layer: LayerSpec = (67, 44), @@ -36,6 +32,31 @@ def npn_W1L2( ) -> gf.Component: """Return npn device with emitter size 1*2. + Args: + E_width: width of the emitter. + E_length: length of the emitter. + B_width: width of the base. + C_width: width of the collector. + np_spacing: spacing between np regions. + diffusion_layer: layer of the diffusion. + tap_layer: layer of the tap. + diff_enclosure: enclosure of the diffusion. + contact_size: size of the contact. + contact_spacing: spacing between the contacts. + contact_layer: layer of the contact. + contact_enclosure: enclosure of the contact. + pwell_layer: layer of the pwell. + dnwell_layer: layer of the dnwell. + sdm_enclosure: enclosure of the sdm. + nsdm_layer: layer of the nsdm. + psdm_layer: layer of the psdm. + npn_layer: layer of the npn. + li_layer: layer of the local interconnect. + li_enclosure: enclosure of the local interconnect. + mcon_layer: layer of the mcon. + mcon_enclosure: enclosure of the mcon. + m1_layer: layer of the metal1. + .. plot:: :include-source: @@ -169,10 +190,14 @@ def npn_W1L2( B_in = c_B.add_ref(rect_B_in) B_out = c_B.add_ref(rect_B_out) - B_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + B_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) B_in.dmovex(E_width + np_spacing) - B_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + B_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) B_out.dmovex(E_width + np_spacing + B_width) c.add_ref(gf.boolean(A=B_out, B=B_in, operation="A-B", layer=tap_layer)) @@ -197,10 +222,14 @@ def npn_W1L2( pmB_in = c_B.add_ref(rect_pmB_in) pmB_out = c_B.add_ref(rect_pmB_out) - pmB_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + pmB_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) pmB_in.dmovex(E_width + np_spacing - sdm_enclosure[0]) - pmB_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + pmB_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) pmB_out.dmovex(E_width + np_spacing + B_width + sdm_enclosure[1]) c.add_ref(gf.boolean(A=pmB_out, B=pmB_in, operation="A-B", layer=psdm_layer)) @@ -285,7 +314,9 @@ def npn_W1L2( li_m1_b_in = c_B.add_ref(rect_in) li_m1_b_out = c_B.add_ref(rect_out) - li_m1_b_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_b_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_b_in.dmovex( ( E_width @@ -297,7 +328,9 @@ def npn_W1L2( - (1 - i) * li_enclosure ) - li_m1_b_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_b_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_b_out.dmovex( ( E_width @@ -451,10 +484,14 @@ def npn_W1L2( C_in = c_C.add_ref(rect_C_in) C_out = c_C.add_ref(rect_C_out) - C_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + C_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) C_in.dmovex(E_width + 2.25 * np_spacing + B_width) - C_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + C_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) C_out.dmovex(E_width + 2.25 * np_spacing + B_width + C_width) c.add_ref(gf.boolean(A=C_out, B=C_in, operation="A-B", layer=tap_layer)) @@ -487,10 +524,14 @@ def npn_W1L2( nmC_in = c_C.add_ref(rect_nmC_in) nmC_out = c_C.add_ref(rect_nmC_out) - nmC_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + nmC_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nmC_in.dmovex(E_width + 2.25 * np_spacing + B_width - sdm_enclosure[0]) - nmC_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + nmC_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nmC_out.dmovex(E_width + 2.25 * np_spacing + B_width + C_width + sdm_enclosure[0]) c.add_ref(gf.boolean(A=nmC_out, B=nmC_in, operation="A-B", layer=nsdm_layer)) @@ -576,7 +617,9 @@ def npn_W1L2( li_m1_c_in = c_C.add_ref(rect_in) li_m1_c_out = c_C.add_ref(rect_out) - li_m1_c_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_c_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_c_in.dmovex( E_width + 2.25 * np_spacing @@ -586,7 +629,9 @@ def npn_W1L2( - (1 - i) * li_enclosure ) - li_m1_c_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_c_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_c_out.dmovex( E_width + 2.25 * np_spacing @@ -752,7 +797,9 @@ def npn_W1L2( layer=pwell_layer, ) pwell = c.add_ref(rect_pwell) - pwell.connect("e1", B_out.ports["e3"], allow_layer_mismatch=True) + pwell.connect( + "e1", B_out.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) pwell.dmovex(B_out.dxmax - B_out.dxmin + diff_enclosure[0]) # generating deep nwell @@ -764,7 +811,9 @@ def npn_W1L2( layer=dnwell_layer, ) dnwell = c.add_ref(rect_dnw) - dnwell.connect("e1", C_out.ports["e3"], allow_layer_mismatch=True) + dnwell.connect( + "e1", C_out.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) dnwell.dmovex(C_out.dxmax - C_out.dxmin + diff_enclosure[0]) # generating npn identifier @@ -773,9 +822,10 @@ def npn_W1L2( size=(C_out.dxmax - C_out.dxmin, C_out.dymax - C_out.dymin), layer=npn_layer ) ) - npn.connect("e1", C_out.ports["e3"], allow_layer_mismatch=True) + npn.connect( + "e1", C_out.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) npn.dmovex(C_out.dxmax - C_out.dxmin) - return c diff --git a/sky130/pcells/p_n_poly.py b/sky130/pcells/p_n_poly.py index 2f0d769a8..d040f0688 100644 --- a/sky130/pcells/p_n_poly.py +++ b/sky130/pcells/p_n_poly.py @@ -31,6 +31,31 @@ def p_n_poly( ) -> gf.Component: """Return p- poly resistor with sheet resistance of 2000 ohms/square. + Args: + p_poly_width: width of the p- poly resistor. + p_poly_length: length of the p- poly resistor. + poly_res_layer: layer of the p- poly resistor. + poly_layer: layer of the polysilicon. + psdm_layer: layer of the p+ implants. + sdm_enclosure: enclosure of the p+ implants. + contact_size: size of the contact. + contact_spacing: spacing between the contacts. + licon_slots_size: size of the licon slots. + licon_slots_spacing: spacing between the licon slots. + contact_layer: layer of the contacts. + contact_enclosure: enclosure of the contacts. + li_layer: layer of the local interconnects. + li_enclosure: enclosure of the local interconnects. + mcon_layer: layer of the mcon. + mcon_enclosure: enclosure of the mcon. + m1_layer: layer of the m1. + urpm_layer: layer of the poly resistor implant. + urpm_min_width: minimum width of the poly resistor implant. + urpm_enclosure: enclosure of the poly resistor implant. + npc_layer: layer of the nitride poly cut. + npc_enclosure: enclosure of the nitride poly cut. + + .. plot:: :include-source: @@ -191,7 +216,9 @@ def p_n_poly( layer=npc_layer, ) npc = c.add_ref(rect_npc) - npc.connect("e1", R_0.ports["e1"], allow_layer_mismatch=True) + npc.connect( + "e1", R_0.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) npc.dmovex(p_poly_width + npc_enclosure[0]) # generate rpm (poly resistor implant) @@ -206,7 +233,9 @@ def p_n_poly( size=(urpm_width, urpm_length), layer=urpm_layer ) urpm = c.add_ref(rect_urpm) - urpm.connect("e1", R_0.ports["e1"], allow_layer_mismatch=True) + urpm.connect( + "e1", R_0.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) urpm.dmovex(p_poly_width + ((urpm_width - p_poly_width) / 2)) # generate p+ implants @@ -215,9 +244,10 @@ def p_n_poly( layer=psdm_layer, ) psdm = c.add_ref(rect_psdm) - psdm.connect("e1", urpm.ports["e3"], allow_layer_mismatch=True) + psdm.connect( + "e1", urpm.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) psdm.dmovex(urpm_width + sdm_enclosure[0]) - return c diff --git a/sky130/pcells/p_p_poly.py b/sky130/pcells/p_p_poly.py index da34c35b3..be7e19556 100644 --- a/sky130/pcells/p_p_poly.py +++ b/sky130/pcells/p_p_poly.py @@ -33,6 +33,28 @@ def p_p_poly( Args: p_poly_width: in um. + p_poly_length: in um. + poly_res_layer: layer of the p+ poly resistor. + poly_layer: layer of the polysilicon. + psdm_layer: layer of the p+ implants. + sdm_enclosure: enclosure of the p+ implants. + contact_size: size of the contact. + contact_spacing: spacing between the contacts. + licon_slots_size: size of the licon slots. + licon_slots_spacing: spacing between the licon slots. + contact_layer: layer of the contacts. + contact_enclosure: enclosure of the contacts. + li_layer: layer of the local interconnects. + li_enclosure: enclosure of the local interconnects. + mcon_layer: layer of the mcon. + mcon_enclosure: enclosure of the mcon. + m1_layer: layer of the m1. + rpm_layer: layer of the poly resistor implant. + rpm_min_width: minimum width of the poly resistor implant. + rpm_enclosure: enclosure of the poly resistor implant. + npc_layer: layer of the nitride poly cut. + npc_enclosure: enclosure of the nitride poly cut. + .. plot:: :include-source: @@ -196,7 +218,9 @@ def p_p_poly( layer=npc_layer, ) npc = c.add_ref(rect_npc) - npc.connect("e1", R_0.ports["e1"], allow_layer_mismatch=True) + npc.connect( + "e1", R_0.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) npc.dmovex(p_poly_width + npc_enclosure[0]) # generate rpm (poly resistor implant) @@ -209,7 +233,9 @@ def p_p_poly( rect_rpm = gf.components.rectangle(size=(rpm_width, rpm_length), layer=rpm_layer) rpm = c.add_ref(rect_rpm) - rpm.connect("e1", R_0.ports["e1"], allow_layer_mismatch=True) + rpm.connect( + "e1", R_0.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) rpm.dmovex(p_poly_width + ((rpm_width - p_poly_width) / 2)) # generate p+ implants @@ -218,7 +244,9 @@ def p_p_poly( layer=psdm_layer, ) psdm = c.add_ref(rect_psdm) - psdm.connect("e1", rpm.ports["e3"], allow_layer_mismatch=True) + psdm.connect( + "e1", rpm.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) psdm.dmovex(rpm_width + sdm_enclosure[0]) return c diff --git a/sky130/pcells/pmos.py b/sky130/pcells/pmos.py index aa1895665..64148e549 100644 --- a/sky130/pcells/pmos.py +++ b/sky130/pcells/pmos.py @@ -304,7 +304,9 @@ def pmos( # 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", diff_p.ports["e3"], allow_layer_mismatch=True) + diff_n.connect( + "e1", diff_p.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) diff_n.dmovex(diff_spacing + sdm_spacing) cont_arr4 = c.add_ref(rect_c, rows=nr, columns=nc, spacing=con_sp) @@ -373,7 +375,9 @@ def pmos( layer=nsdm_layer, ) nsdm = c.add_ref(rect_nm) - nsdm.connect("e1", diff_p.ports["e3"], allow_layer_mismatch=True) + nsdm.connect( + "e1", diff_p.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nsdm.dmovex(diff_spacing + sdm_spacing - sdm_enclosure[0]) # generating nwell diff --git a/sky130/pcells/pmos_5v.py b/sky130/pcells/pmos_5v.py index 66f98f2a6..0670ac209 100644 --- a/sky130/pcells/pmos_5v.py +++ b/sky130/pcells/pmos_5v.py @@ -46,14 +46,28 @@ def pmos_5v( 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 + 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. + sdm_enclosure: for source drain metal. + nsdm_layer: for source drain metal. + psdm_layer: for source drain metal. + sdm_spacing: for source drain metal. + hvi_layer: for high voltage implant. + li_width: for local interconnect. + li_layer: for local interconnect. + li_enclosure: for local interconnect. + mcon_layer: for metal contact. + mcon_enclosure: for metal contact. + m1_layer: for metal1. + npc_layer: for poly contact. + npc_spacing: for poly contact. + .. plot:: :include-source: @@ -261,7 +275,9 @@ def pmos_5v( # 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", diff_p.ports["e3"], allow_layer_mismatch=True) + diff_n.connect( + "e1", diff_p.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) diff_n.dmovex(diff_spacing + sdm_spacing) cont_arr4 = c.add_ref(rect_c, rows=nr, columns=nc, spacing=con_sp) @@ -330,7 +346,9 @@ def pmos_5v( layer=nsdm_layer, ) nsdm = c.add_ref(rect_nm) - nsdm.connect("e1", diff_p.ports["e3"], allow_layer_mismatch=True) + nsdm.connect( + "e1", diff_p.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nsdm.dmovex(diff_spacing + sdm_spacing - sdm_enclosure[0]) # generating nwell @@ -368,7 +386,6 @@ def pmos_5v( dnwell = c.add_ref(rect_hv) dnwell.dmovex(-diff_enclosure[0] - dnwell_enclosure[0]) dnwell.dmovey(-diff_enclosure[1] - dnwell_enclosure[1]) - return c diff --git a/sky130/pcells/pnp.py b/sky130/pcells/pnp.py index 19bd5d212..adb1f1ffc 100644 --- a/sky130/pcells/pnp.py +++ b/sky130/pcells/pnp.py @@ -31,6 +31,29 @@ def pnp( ) -> gf.Component: """Return pnp. + Args: + E_width: Emitter width. + E_length: Emitter length. + B_width: Base width. + C_width: Collector width. + np_spacing: Spacing between N+ and P+ implants. + diffusion_layer: Layer for the diffusion. + tap_layer: Layer for the tap. + diff_enclosure: Enclosure for the diffusion. + contact_size: Contact size. + contact_spacing: Contact spacing. + contact_layer: Layer for the contact. + contact_enclosure: Enclosure for the contact. + nwell_layer: Layer for the nwell. + sdm_enclosure: Enclosure for the source/drain implants. + nsdm_layer: Layer for the n+ source/drain implants. + psdm_layer: Layer for the p+ source/drain implants. + pnp_layer: Layer for the pnp. + li_layer: Layer for the local interconnect. + li_enclosure: Enclosure for the local interconnect. + mcon_layer: Layer for the mcon. + mcon_enclosure: Enclosure for the mcon. + m1_layer: Layer for the metal1. .. plot:: :include-source: @@ -143,10 +166,14 @@ def pnp( B_in = c_B.add_ref(rect_B_in) B_out = c_B.add_ref(rect_B_out) - B_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + B_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) B_in.dmovex(E_width + np_spacing) - B_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + B_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) B_out.dmovex(E_width + np_spacing + B_width) c.add_ref(gf.boolean(A=B_out, B=B_in, operation="not", layer=tap_layer)) @@ -171,10 +198,14 @@ def pnp( nmB_in = c_B.add_ref(rect_nmB_in) nmB_out = c_B.add_ref(rect_nmB_out) - nmB_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + nmB_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nmB_in.dmovex(E_width + np_spacing - sdm_enclosure[0]) - nmB_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + nmB_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nmB_out.dmovex(E_width + np_spacing + B_width + sdm_enclosure[1]) c.add_ref(gf.boolean(A=nmB_out, B=nmB_in, operation="not", layer=nsdm_layer)) @@ -258,7 +289,9 @@ def pnp( li_m1_b_in = c_B.add_ref(rect_in) li_m1_b_out = c_B.add_ref(rect_out) - li_m1_b_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_b_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_b_in.dmovex( ( E_width @@ -270,7 +303,9 @@ def pnp( - (1 - i) * li_enclosure ) - li_m1_b_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_b_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_b_out.dmovex( ( E_width @@ -424,10 +459,14 @@ def pnp( C_in = c_C.add_ref(rect_C_in) C_out = c_C.add_ref(rect_C_out) - C_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + C_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) C_in.dmovex(E_width + 2.25 * np_spacing + B_width) - C_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + C_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) C_out.dmovex(E_width + 2.25 * np_spacing + B_width + C_width) c.add_ref(gf.boolean(A=C_out, B=C_in, operation="not", layer=tap_layer)) @@ -460,10 +499,14 @@ def pnp( pmC_in = c_C.add_ref(rect_pmC_in) pmC_out = c_C.add_ref(rect_pmC_out) - pmC_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + pmC_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) pmC_in.dmovex(E_width + 2.25 * np_spacing + B_width - sdm_enclosure[0]) - pmC_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + pmC_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) pmC_out.dmovex(E_width + 2.25 * np_spacing + B_width + C_width + sdm_enclosure[0]) c.add_ref(gf.boolean(A=pmC_out, B=pmC_in, operation="A-B", layer=psdm_layer)) @@ -549,7 +592,9 @@ def pnp( li_m1_c_in = c_C.add_ref(rect_in) li_m1_c_out = c_C.add_ref(rect_out) - li_m1_c_in.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_c_in.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_c_in.dmovex( E_width + 2.25 * np_spacing @@ -559,7 +604,9 @@ def pnp( - (1 - i) * li_enclosure ) - li_m1_c_out.connect("e1", E.ports["e1"], allow_layer_mismatch=True) + li_m1_c_out.connect( + "e1", E.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True + ) li_m1_c_out.dmovex( E_width + 2.25 * np_spacing @@ -725,7 +772,9 @@ def pnp( layer=nwell_layer, ) nwell = c.add_ref(rect_nwell) - nwell.connect("e1", B_out.ports["e3"], allow_layer_mismatch=True) + nwell.connect( + "e1", B_out.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) nwell.dmovex(B_out.dxmax - B_out.dxmin + diff_enclosure[0]) # generating pnp identifier @@ -734,7 +783,9 @@ def pnp( size=(C_out.dxmax - C_out.dxmin, C_out.dymax - C_out.dymin), layer=pnp_layer ) ) - npn.connect("e1", C_out.ports["e3"], allow_layer_mismatch=True) + npn.connect( + "e1", C_out.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True + ) npn.dmovex(C_out.dxmax - C_out.dxmin) return c diff --git a/sky130/pcells/via_generator.py b/sky130/pcells/via_generator.py index 32ceab682..bc8d1e518 100644 --- a/sky130/pcells/via_generator.py +++ b/sky130/pcells/via_generator.py @@ -17,6 +17,14 @@ def via_generator( and set number of rows and number of columns as a \ global variable to be used outside the function. + Args: + width: width of the area. + length: length of the area. + via_size: size of the via. + via_layer: layer of the via. + via_enclosure: enclosure of the via. + via_spacing: spacing between the vias. + .. plot:: :include-source: diff --git a/tests/test_components/test_pdk_settings_npn_W1L2_.yml b/tests/test_components/test_pdk_settings_npn_W1L2_.yml index 18b003908..a94163015 100644 --- a/tests/test_components/test_pdk_settings_npn_W1L2_.yml +++ b/tests/test_components/test_pdk_settings_npn_W1L2_.yml @@ -1,5 +1,5 @@ info: {} -name: npn_W1L2_EW1_EL2_BW0p4__41968916 +name: npn_W1L2_EW1_EL2_BW0p4__7e7949df settings: B_width: 0.4 C_width: 0.4 @@ -23,9 +23,6 @@ settings: diffusion_layer: - 65 - 20 - dnwell_enclosure: - - 0.4 - - 0.4 dnwell_layer: - 64 - 18 @@ -33,8 +30,6 @@ settings: li_layer: - 67 - 20 - li_spacing: 0.17 - li_width: 0.17 m1_layer: - 68 - 20 @@ -60,7 +55,6 @@ settings: sdm_enclosure: - 0.125 - 0.125 - sdm_spacing: 0.13 tap_layer: - 65 - 44