From 15687d1ee20aaf8ce9e88d2bdf3fc9ee09e80107 Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Thu, 12 Sep 2024 14:40:44 +0000 Subject: [PATCH 01/17] Added the cascode common source amplifier with interdigitated fingers. --- .../cascode_common_source/__init__.py | 1 + .../cascode_common_source.py | 179 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/__init__.py create mode 100644 openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/__init__.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/__init__.py new file mode 100644 index 000000000..bb5dbc7ae --- /dev/null +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/__init__.py @@ -0,0 +1 @@ +from glayout.flow.blocks.elementary.cascode_common_source.cascode_common_source import cascode_common_source, cascode_common_source_netlist \ No newline at end of file diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py new file mode 100644 index 000000000..9c741b936 --- /dev/null +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -0,0 +1,179 @@ +from glayout.flow.placement.two_transistor_interdigitized import two_nfet_interdigitized, two_pfet_interdigitized +from glayout.flow.pdk.mappedpdk import MappedPDK +from glayout.flow.routing.c_route import c_route +from glayout.flow.routing.L_route import L_route +from glayout.flow.routing.straight_route import straight_route +from glayout.flow.spice.netlist import Netlist +from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130 +from glayout.flow.primitives.fet import nmos, pmos +from glayout.flow.primitives.guardring import tapring +from glayout.flow.pdk.util.port_utils import add_ports_perimeter +from gdsfactory.component import Component +from typing import Optional, Union + + +def cascode_common_source_netlist( + pdk: MappedPDK, + width: float, + length: float, + multipliers: int, + n_or_p_fet: Optional[str] = 'nfet', + subckt_only: Optional[bool] = False +) -> Netlist: + if length is None: + length = pdk.get_grule('poly')['min_width'] + if width is None: + width = 3 + mtop = multipliers if subckt_only else 1 + model = pdk.models[n_or_p_fet] + + source_netlist = """.subckt {circuit_name} {nodes} """ + f'l={length} w={width} m={mtop} ' + """ +XA VREF VREF VSS VB {model} l={{l}} w={{w}} m={{m}} +XB VCOPY VREF VSS VB {model} l={{l}} w={{w}} m={{m}}""" + source_netlist += "\n.ends {circuit_name}" + + instance_format = "X{name} {nodes} {circuit_name} l={length} w={width} m={mult}" + + return Netlist( + circuit_name='CASCODECOMMONSRC', + nodes=['VREF', 'VCOPY', 'VSS', 'VB'], + source_netlist=source_netlist, + instance_format=instance_format, + parameters={ + 'model': model, + 'width': width, + 'length': length, + 'mult': multipliers + } + ) + + +#@cell +def cascode_common_source( + pdk: MappedPDK, + numcols: int = 3, + device: str = 'nfet', + with_dummy: Optional[bool] = True, + with_substrate_tap: Optional[bool] = False, + with_tie: Optional[bool] = True, + tie_layers: tuple[str,str]=("met2","met1"), + **kwargs +) -> Component: + """An instantiable cascode common source amplifier that returns a Component object. + The cascode common source amplifier could be a two transistor interdigitized structure with a shorted source and gate. + It can be instantiated with either nmos or pmos devices. It can also be instantiated with a dummy device, a substrate tap, and a tie layer, and is centered at the origin. + Transistor A acts as the reference and Transistor B acts as the mirror fet + Transistor M1 acts as the input transistor and Transistor M2 acts as the cascoded output transistor fet which determines the output impedance. + + Args: + pdk (MappedPDK): the process design kit to use + numcols (int): number of columns of the interdigitized fets + device (str): nfet or pfet (can only interdigitize one at a time with this option) + with_dummy (bool): True places dummies on either side of the interdigitized fets + with_substrate_tap (bool): boolean to decide whether to place a substrate tapring + with_tie (bool): boolean to decide whether to place a tapring for tielayer + tie_layers (tuple[str,str], optional): the layers to use for the tie. Defaults to ("met2","met1"). + **kwargs: The keyword arguments are passed to the two_nfet_interdigitized or two_pfet_interdigitized functions and need to be valid arguments that can be accepted by the multiplier function + + Returns: + Component: a cascode common source amplifier component object + """ + top_level = Component("cascode common source amplifier") + if device in ['nmos', 'nfet']: + interdigitized_fets = two_nfet_interdigitized( + pdk, + numcols=numcols, + dummy=with_dummy, + with_substrate_tap=False, + with_tie=False, + **kwargs + ) + elif device in ['pmos', 'pfet']: + interdigitized_fets = two_pfet_interdigitized( + pdk, + numcols=numcols, + dummy=with_dummy, + with_substrate_tap=False, + with_tie=False, + **kwargs + ) + top_level.add_ports(interdigitized_fets.get_ports_list(), prefix="fet_") + maxmet_sep = pdk.util_max_metal_seperation() + # short source of the fets + source_short = interdigitized_fets << c_route(pdk, interdigitized_fets.ports['A_source_E'], interdigitized_fets.ports['B_source_E'], extension=3*maxmet_sep, viaoffset=False) + # short gates of the fets + gate_short = interdigitized_fets << c_route(pdk, interdigitized_fets.ports['A_gate_W'], interdigitized_fets.ports['B_gate_W'], extension=3*maxmet_sep, viaoffset=False) + # short gate and drain of one of the reference + interdigitized_fets << L_route(pdk, interdigitized_fets.ports['A_drain_W'], gate_short.ports['con_N'], viaoffset=False, fullbottom=False) + + top_level << interdigitized_fets + # add the tie layer + if with_tie: + tap_sep = max( + pdk.util_max_metal_seperation(), + pdk.get_grule("active_diff", "active_tap")["min_separation"], + ) + tap_sep += pdk.get_grule("p+s/d", "active_tap")["min_enclosure"] + tap_encloses = ( + 2 * (tap_sep + interdigitized_fets.xmax), + 2 * (tap_sep + interdigitized_fets.ymax), + ) + tie_ref = top_level << tapring(pdk, enclosed_rectangle = tap_encloses, sdlayer = "p+s/d", horizontal_glayer = tie_layers[0], vertical_glayer = tie_layers[1]) + top_level.add_ports(tie_ref.get_ports_list(), prefix="welltie_") + try: + top_level << straight_route(pdk, top_level.ports["A_0_dummy_L_gsdcon_top_met_W"],top_level.ports["welltie_W_top_met_W"],glayer2="met1") + except KeyError: + pass + try: + end_col = numcols - 1 + port1 = f'B_{end_col}_dummy_R_gdscon_top_met_E' + top_level << straight_route(pdk, top_level.ports[port1], top_level.ports["welltie_E_top_met_E"], glayer2="met1") + except KeyError: + pass + + # add a pwell + top_level.add_padding(layers = (pdk.get_glayer("pwell"),), default = pdk.get_grule("pwell", "active_tap")["min_enclosure"], ) + top_level = add_ports_perimeter(top_level, layer = pdk.get_glayer("pwell"), prefix="well_") + + # add the substrate tap if specified + if with_substrate_tap: + subtap_sep = pdk.get_grule("dnwell", "active_tap")["min_separation"] + subtap_enclosure = ( + 2.5 * (subtap_sep + interdigitized_fets.xmax), + 2.5 * (subtap_sep + interdigitized_fets.ymax), + ) + subtap_ring = top_level << tapring(pdk, enclosed_rectangle = subtap_enclosure, sdlayer = "p+s/d", horizontal_glayer = "met2", vertical_glayer = "met1") + top_level.add_ports(subtap_ring.get_ports_list(), prefix="substrate_tap_") + + top_level.add_ports(source_short.get_ports_list(), prefix='purposegndports') + + + top_level.info['netlist'] = cascode_common_source_netlist( + pdk, + width=kwargs.get('width', 3), length=kwargs.get('length', 1), multipliers=numcols, + n_or_p_fet=device, + subckt_only=True + ) + + return top_level + + +mapped_pdk_build = sky130 +Cascode_cs_component = cascode_common_source(mapped_pdk_build, + numcols=10) #(mapped_pdk_build,2,3,4,6, cs_type="pfet") +Cascode_cs_component.show() + +# magic_drc_result = sky130.drc_magic(Cascode_cs_component, Cascode_cs_component.name) +# if magic_drc_result : +# print("DRC is clean: ", magic_drc_result) +# else: +# print("DRC failed. Please try again.") + + +# netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, 'cascode_common_source') +# netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, cascode_common_source.sch) +# netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, Cascode_cs_component.name) +#Cascode_cs_component.name = 'cs_two_stack' +#netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, cs_two_stack.name) +#print(f"LVS results", netgen_lvs_result) + From c3fe9f81a872080c0b10e517d4d20ff06d72c0b1 Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Thu, 12 Sep 2024 16:17:01 +0000 Subject: [PATCH 02/17] Added the M1 and M2 FETs to top_level component. Reference added to move the M2 north of M1. --- .../cascode_common_source.py | 168 +++++++++++------- 1 file changed, 101 insertions(+), 67 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 9c741b936..dcf6090dc 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -12,6 +12,8 @@ from typing import Optional, Union +from glayout.flow.pdk.util.comp_utils import prec_ref_center, prec_center, movey, evaluate_bbox + def cascode_common_source_netlist( pdk: MappedPDK, width: float, @@ -80,80 +82,112 @@ def cascode_common_source( """ top_level = Component("cascode common source amplifier") if device in ['nmos', 'nfet']: - interdigitized_fets = two_nfet_interdigitized( - pdk, - numcols=numcols, - dummy=with_dummy, - with_substrate_tap=False, - with_tie=False, - **kwargs - ) + fet_M1=nmos(pdk, + with_tie=False, + with_dummy=with_dummy, + with_substrate_tap=False, + **kwargs) + fet_M2=nmos(pdk, + with_tie=False, + with_dummy=with_dummy, + with_substrate_tap=False, + **kwargs) elif device in ['pmos', 'pfet']: - interdigitized_fets = two_pfet_interdigitized( - pdk, - numcols=numcols, - dummy=with_dummy, - with_substrate_tap=False, - with_tie=False, - **kwargs - ) - top_level.add_ports(interdigitized_fets.get_ports_list(), prefix="fet_") - maxmet_sep = pdk.util_max_metal_seperation() - # short source of the fets - source_short = interdigitized_fets << c_route(pdk, interdigitized_fets.ports['A_source_E'], interdigitized_fets.ports['B_source_E'], extension=3*maxmet_sep, viaoffset=False) - # short gates of the fets - gate_short = interdigitized_fets << c_route(pdk, interdigitized_fets.ports['A_gate_W'], interdigitized_fets.ports['B_gate_W'], extension=3*maxmet_sep, viaoffset=False) - # short gate and drain of one of the reference - interdigitized_fets << L_route(pdk, interdigitized_fets.ports['A_drain_W'], gate_short.ports['con_N'], viaoffset=False, fullbottom=False) + fet_M1=pmos(pdk, + with_tie=False, + with_dummy=with_dummy, + with_substrate_tap=False, + **kwargs) + fet_M2=pmos(pdk, + with_tie=False, + with_dummy=with_dummy, + with_substrate_tap=False, + **kwargs) + print("FETS are instantiated now") + + + # top_level.add(fet_M1) + # top_level.add(fet_M2) + + top_level << fet_M1 + top_level << fet_M2 + + M1_ref = prec_ref_center(fet_M1) + M2_ref = prec_ref_center(fet_M2) + movey(M2_ref, 0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1]) + pdk.util_max_metal_seperation()) + - top_level << interdigitized_fets - # add the tie layer - if with_tie: - tap_sep = max( - pdk.util_max_metal_seperation(), - pdk.get_grule("active_diff", "active_tap")["min_separation"], - ) - tap_sep += pdk.get_grule("p+s/d", "active_tap")["min_enclosure"] - tap_encloses = ( - 2 * (tap_sep + interdigitized_fets.xmax), - 2 * (tap_sep + interdigitized_fets.ymax), - ) - tie_ref = top_level << tapring(pdk, enclosed_rectangle = tap_encloses, sdlayer = "p+s/d", horizontal_glayer = tie_layers[0], vertical_glayer = tie_layers[1]) - top_level.add_ports(tie_ref.get_ports_list(), prefix="welltie_") - try: - top_level << straight_route(pdk, top_level.ports["A_0_dummy_L_gsdcon_top_met_W"],top_level.ports["welltie_W_top_met_W"],glayer2="met1") - except KeyError: - pass - try: - end_col = numcols - 1 - port1 = f'B_{end_col}_dummy_R_gdscon_top_met_E' - top_level << straight_route(pdk, top_level.ports[port1], top_level.ports["welltie_E_top_met_E"], glayer2="met1") - except KeyError: - pass + # top_level< Date: Thu, 19 Sep 2024 10:05:30 +0000 Subject: [PATCH 03/17] Added reference to the input and cascode transistor with options for horizontal or vertical placement. --- .../cascode_common_source.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index dcf6090dc..aae392ab6 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -81,6 +81,7 @@ def cascode_common_source( Component: a cascode common source amplifier component object """ top_level = Component("cascode common source amplifier") + # Create the transistors if device in ['nmos', 'nfet']: fet_M1=nmos(pdk, with_tie=False, @@ -105,18 +106,23 @@ def cascode_common_source( **kwargs) print("FETS are instantiated now") + # Added references to the two FETs within the component level + M1_ref = top_level << fet_M1 + M2_ref = top_level << fet_M2 + # Placement + M1_ref_centre_coord = prec_ref_center(fet_M1) + M2_ref_centre_coord = prec_ref_center(fet_M2) + place_devices='H' + if place_devices in ['lateral', 'horizontal', 'H']: + M2_ref.movex(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) + if place_devices in ['vertical', 'V']: + M2_ref.movey(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) - # top_level.add(fet_M1) - # top_level.add(fet_M2) - - top_level << fet_M1 - top_level << fet_M2 - - M1_ref = prec_ref_center(fet_M1) - M2_ref = prec_ref_center(fet_M2) - movey(M2_ref, 0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1]) + pdk.util_max_metal_seperation()) - - + # Routing and Port definitions + if place_devices in ['lateral', 'horizontal', 'H']: + top_level << straight_route(pdk, M1_ref.ports["multiplier_0_gate_E"], M2_ref.ports["multiplier_0_gate_W"]) + if place_devices in ['vertical', 'V']: + top_level << c_route(pdk, M1_ref.ports["multiplier_0_gate_W"], M2_ref.ports["multiplier_0_gate_W"]) # top_level< Date: Thu, 19 Sep 2024 10:29:27 +0000 Subject: [PATCH 04/17] Source of M2 connected to Drain of M1 with generic port definition. --- .../cascode_common_source/cascode_common_source.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index aae392ab6..362c9f370 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -112,7 +112,7 @@ def cascode_common_source( # Placement M1_ref_centre_coord = prec_ref_center(fet_M1) M2_ref_centre_coord = prec_ref_center(fet_M2) - place_devices='H' + place_devices='V' if place_devices in ['lateral', 'horizontal', 'H']: M2_ref.movex(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) if place_devices in ['vertical', 'V']: @@ -120,9 +120,13 @@ def cascode_common_source( # Routing and Port definitions if place_devices in ['lateral', 'horizontal', 'H']: - top_level << straight_route(pdk, M1_ref.ports["multiplier_0_gate_E"], M2_ref.ports["multiplier_0_gate_W"]) + top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: - top_level << c_route(pdk, M1_ref.ports["multiplier_0_gate_W"], M2_ref.ports["multiplier_0_gate_W"]) + top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) + + # top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") + # top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") + # top_level< Date: Thu, 19 Sep 2024 12:23:32 +0000 Subject: [PATCH 05/17] Added port prefix M1 and M2 . --- .../cascode_common_source/cascode_common_source.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 362c9f370..5b7cdaf63 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -117,16 +117,22 @@ def cascode_common_source( M2_ref.movex(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) if place_devices in ['vertical', 'V']: M2_ref.movey(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) + + + top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") + top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") + # print(top_level.get_ports_list()) + + print("Getting dict list of ports: ", top_level.ports) # Routing and Port definitions if place_devices in ['lateral', 'horizontal', 'H']: top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) + #So now how do I attach net names to M1_multiplier_0_Gate_W to Vin, M1_multiplier_0_Source_S to Vss, + # M2_multiplier_0_Drain_N to Iout, M2_multiplier_0_Gate_W to Vbias. - # top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") - # top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") - # top_level< Date: Thu, 19 Sep 2024 13:42:51 +0000 Subject: [PATCH 06/17] Removed comments --- .../cascode_common_source.py | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 5b7cdaf63..b4210d060 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -30,15 +30,15 @@ def cascode_common_source_netlist( model = pdk.models[n_or_p_fet] source_netlist = """.subckt {circuit_name} {nodes} """ + f'l={length} w={width} m={mtop} ' + """ -XA VREF VREF VSS VB {model} l={{l}} w={{w}} m={{m}} -XB VCOPY VREF VSS VB {model} l={{l}} w={{w}} m={{m}}""" +XM1 INT VIN VSS VSS {model} l={{l}} w={{w}} m={{m}} +XM2 IOUT VBIAS INT VSS {model} l={{l}} w={{w}} m={{m}}""" source_netlist += "\n.ends {circuit_name}" instance_format = "X{name} {nodes} {circuit_name} l={length} w={width} m={mult}" return Netlist( circuit_name='CASCODECOMMONSRC', - nodes=['VREF', 'VCOPY', 'VSS', 'VB'], + nodes=['VIN', 'VBIAS', 'VSS', 'IOUT'], source_netlist=source_netlist, instance_format=instance_format, parameters={ @@ -123,7 +123,7 @@ def cascode_common_source( top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") # print(top_level.get_ports_list()) - print("Getting dict list of ports: ", top_level.ports) + # print("Getting dict list of ports: ", top_level.ports) # Routing and Port definitions if place_devices in ['lateral', 'horizontal', 'H']: @@ -133,20 +133,7 @@ def cascode_common_source( #So now how do I attach net names to M1_multiplier_0_Gate_W to Vin, M1_multiplier_0_Source_S to Vss, # M2_multiplier_0_Drain_N to Iout, M2_multiplier_0_Gate_W to Vbias. - # top_level< Date: Thu, 19 Sep 2024 14:23:40 +0000 Subject: [PATCH 07/17] LVS fails. --- .../cascode_common_source/cascode_common_source.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index b4210d060..e81ed994d 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -206,12 +206,7 @@ def cascode_common_source( else: print("DRC failed. Please try again.") -## Checking netlist -print("Netlist: ",Cascode_cs_component.info['netlist'].source_netlist) -# netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, 'cascode_common_source') -# netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, cascode_common_source.sch) -# netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, Cascode_cs_component.name) -#Cascode_cs_component.name = 'cs_two_stack' -#netgen_lvs_result = sky130_mapped_pdk.lvs_netgen(Cascode_cs_component, cs_two_stack.name) -#print(f"LVS results", netgen_lvs_result) +Cascode_cs_component.name = 'cascode_common_source_lvs' +netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') +print(f"LVS results", netgen_lvs_result) From ce4255191ef51d450cac0649c01c64ced82f9b7c Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Thu, 19 Sep 2024 14:53:09 +0000 Subject: [PATCH 08/17] LVS fail again. --- .../elementary/cascode_common_source/cascode_common_source.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index e81ed994d..04ce45a57 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -130,8 +130,7 @@ def cascode_common_source( top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) - #So now how do I attach net names to M1_multiplier_0_Gate_W to Vin, M1_multiplier_0_Source_S to Vss, - # M2_multiplier_0_Drain_N to Iout, M2_multiplier_0_Gate_W to Vbias. + #So now I attach pin names for port # top_level.add_ports(interdigitized_fets.get_ports_list(), prefix="fet_") From 7340dcc5f071cb3be82a7c520fb1e88922a5b4b5 Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Mon, 23 Sep 2024 22:56:03 +0000 Subject: [PATCH 09/17] Multiple fingers and multipliers supported for the NMOS/PMOS devices. --- .../cascode_common_source.py | 89 ++++++------------- 1 file changed, 28 insertions(+), 61 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 04ce45a57..e0d5c8fe8 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -10,7 +10,7 @@ from glayout.flow.pdk.util.port_utils import add_ports_perimeter from gdsfactory.component import Component from typing import Optional, Union - +from gdsfactory.components import text_freetype, rectangle from glayout.flow.pdk.util.comp_utils import prec_ref_center, prec_center, movey, evaluate_bbox @@ -55,6 +55,10 @@ def cascode_common_source( pdk: MappedPDK, numcols: int = 3, device: str = 'nfet', + m1_fingers: int = 1, + m1_multipliers: int = 1, + m2_fingers: int = 1, + m2_multipliers: int = 1, with_dummy: Optional[bool] = True, with_substrate_tap: Optional[bool] = False, with_tie: Optional[bool] = True, @@ -84,22 +88,30 @@ def cascode_common_source( # Create the transistors if device in ['nmos', 'nfet']: fet_M1=nmos(pdk, - with_tie=False, - with_dummy=with_dummy, - with_substrate_tap=False, - **kwargs) + fingers=m1_fingers, + multipliers = m1_multipliers, + with_tie=False, + with_dummy=with_dummy, + with_substrate_tap=False, + **kwargs) fet_M2=nmos(pdk, + fingers=m2_fingers, + multipliers = m2_multipliers, with_tie=False, with_dummy=with_dummy, with_substrate_tap=False, **kwargs) elif device in ['pmos', 'pfet']: fet_M1=pmos(pdk, + fingers=m1_fingers, + multipliers = m1_multipliers, with_tie=False, with_dummy=with_dummy, with_substrate_tap=False, **kwargs) fet_M2=pmos(pdk, + fingers=m2_fingers, + multipliers = m2_multipliers, with_tie=False, with_dummy=with_dummy, with_substrate_tap=False, @@ -121,67 +133,18 @@ def cascode_common_source( top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") - # print(top_level.get_ports_list()) - - # print("Getting dict list of ports: ", top_level.ports) - # Routing and Port definitions if place_devices in ['lateral', 'horizontal', 'H']: top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) #So now I attach pin names for port - - - # top_level.add_ports(interdigitized_fets.get_ports_list(), prefix="fet_") - # maxmet_sep = pdk.util_max_metal_seperation() - # # short source of the fets - # source_short = interdigitized_fets << c_route(pdk, interdigitized_fets.ports['A_source_E'], interdigitized_fets.ports['B_source_E'], extension=3*maxmet_sep, viaoffset=False) - # # short gates of the fets - # gate_short = interdigitized_fets << c_route(pdk, interdigitized_fets.ports['A_gate_W'], interdigitized_fets.ports['B_gate_W'], extension=3*maxmet_sep, viaoffset=False) - # # short gate and drain of one of the reference - # interdigitized_fets << L_route(pdk, interdigitized_fets.ports['A_drain_W'], gate_short.ports['con_N'], viaoffset=False, fullbottom=False) - - # top_level << interdigitized_fets - # # add the tie layer - # if with_tie: - # tap_sep = max( - # pdk.util_max_metal_seperation(), - # pdk.get_grule("active_diff", "active_tap")["min_separation"], - # ) - # tap_sep += pdk.get_grule("p+s/d", "active_tap")["min_enclosure"] - # tap_encloses = ( - # 2 * (tap_sep + interdigitized_fets.xmax), - # 2 * (tap_sep + interdigitized_fets.ymax), - # ) - # tie_ref = top_level << tapring(pdk, enclosed_rectangle = tap_encloses, sdlayer = "p+s/d", horizontal_glayer = tie_layers[0], vertical_glayer = tie_layers[1]) - # top_level.add_ports(tie_ref.get_ports_list(), prefix="welltie_") - # try: - # top_level << straight_route(pdk, top_level.ports["A_0_dummy_L_gsdcon_top_met_W"],top_level.ports["welltie_W_top_met_W"],glayer2="met1") - # except KeyError: - # pass - # try: - # end_col = numcols - 1 - # port1 = f'B_{end_col}_dummy_R_gdscon_top_met_E' - # top_level << straight_route(pdk, top_level.ports[port1], top_level.ports["welltie_E_top_met_E"], glayer2="met1") - # except KeyError: - # pass - - # # add a pwell - # top_level.add_padding(layers = (pdk.get_glayer("pwell"),), default = pdk.get_grule("pwell", "active_tap")["min_enclosure"], ) - # top_level = add_ports_perimeter(top_level, layer = pdk.get_glayer("pwell"), prefix="well_") - - # # add the substrate tap if specified - # if with_substrate_tap: - # subtap_sep = pdk.get_grule("dnwell", "active_tap")["min_separation"] - # subtap_enclosure = ( - # 2.5 * (subtap_sep + interdigitized_fets.xmax), - # 2.5 * (subtap_sep + interdigitized_fets.ymax), - # ) - # subtap_ring = top_level << tapring(pdk, enclosed_rectangle = subtap_enclosure, sdlayer = "p+s/d", horizontal_glayer = "met2", vertical_glayer = "met1") - # top_level.add_ports(subtap_ring.get_ports_list(), prefix="substrate_tap_") - - # top_level.add_ports(source_short.get_ports_list(), prefix='purposegndports') + text_pin_labels = list() + met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) + for name in ['VIN', 'VBIAS', 'VSS', 'IOUT']: + pin_w_label = met5pin.copy() + pin_w_label.add_label(text=name,layer=(72,5),magnification=4) + text_pin_labels.append(pin_w_label) top_level.info['netlist'] = cascode_common_source_netlist( @@ -196,7 +159,11 @@ def cascode_common_source( mapped_pdk_build = sky130 Cascode_cs_component = cascode_common_source(mapped_pdk_build, - numcols=10) #(mapped_pdk_build,2,3,4,6, cs_type="pfet") + m1_fingers=5, + m2_fingers=5, + m1_multipliers=1, + m2_multipliers=1, + numcols=10) Cascode_cs_component.show() magic_drc_result = sky130.drc_magic(Cascode_cs_component, Cascode_cs_component.name) From d3e2f02ed7ea572a35c4970bf7b46d410f941aea Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Mon, 23 Sep 2024 22:58:13 +0000 Subject: [PATCH 10/17] Documentation function updted --- .../elementary/cascode_common_source/cascode_common_source.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index e0d5c8fe8..d485ea36a 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -75,6 +75,8 @@ def cascode_common_source( pdk (MappedPDK): the process design kit to use numcols (int): number of columns of the interdigitized fets device (str): nfet or pfet (can only interdigitize one at a time with this option) + m1_fingers: Number of fingers of M1 transistor + m1_multiplier: Number of multipliers of M1 transistor with_dummy (bool): True places dummies on either side of the interdigitized fets with_substrate_tap (bool): boolean to decide whether to place a substrate tapring with_tie (bool): boolean to decide whether to place a tapring for tielayer From f0ad2deef1faaa289d0f37a5330f4dfda856af08 Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Mon, 23 Sep 2024 23:06:41 +0000 Subject: [PATCH 11/17] comment updated --- .../elementary/cascode_common_source/cascode_common_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index d485ea36a..a49c885c2 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -140,7 +140,7 @@ def cascode_common_source( top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) - #So now I attach pin names for port + #Now attach pin names for port text_pin_labels = list() met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) for name in ['VIN', 'VBIAS', 'VSS', 'IOUT']: From fe2ae5e34009668f484a9b4799a8db409b4fd45a Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Wed, 2 Oct 2024 21:08:00 +0000 Subject: [PATCH 12/17] Adding ports --- .../cascode_common_source.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index a49c885c2..33ce35cf6 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -141,13 +141,18 @@ def cascode_common_source( if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) #Now attach pin names for port - text_pin_labels = list() - met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) - for name in ['VIN', 'VBIAS', 'VSS', 'IOUT']: - pin_w_label = met5pin.copy() - pin_w_label.add_label(text=name,layer=(72,5),magnification=4) - text_pin_labels.append(pin_w_label) + # text_pin_labels = list() + # met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) + # for name in ['VIN', 'VBIAS', 'VSS', 'IOUT']: + # pin_w_label = met5pin.copy() + # pin_w_label.add_label(text=name,layer=(72,5),magnification=4) + # text_pin_labels.append(pin_w_label) + top_level.add_port('VIN', port=fet_M1.ports["multiplier_0_gate_W"]) + top_level.add_port('VBIAS', port=fet_M2.ports["multiplier_0_gate_W"]) + top_level.add_port('VSS', port=fet_M1.ports["multiplier_0_source_S"]) + top_level.add_port('IOUT', port=fet_M2.ports["multiplier_0_drain_N"]) + top_level.info['netlist'] = cascode_common_source_netlist( pdk, @@ -161,8 +166,8 @@ def cascode_common_source( mapped_pdk_build = sky130 Cascode_cs_component = cascode_common_source(mapped_pdk_build, - m1_fingers=5, - m2_fingers=5, + m1_fingers=10, + m2_fingers=10, m1_multipliers=1, m2_multipliers=1, numcols=10) From 32e2fcdc1396ba86c021d8af2c9f5d751043b1ab Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Thu, 3 Oct 2024 16:34:19 +0000 Subject: [PATCH 13/17] Adding ports --- .../cascode_common_source.py | 74 ++++++++++++++++--- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 33ce35cf6..7fd376d17 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -12,7 +12,7 @@ from typing import Optional, Union from gdsfactory.components import text_freetype, rectangle -from glayout.flow.pdk.util.comp_utils import prec_ref_center, prec_center, movey, evaluate_bbox +from glayout.flow.pdk.util.comp_utils import prec_ref_center, prec_center, movey, evaluate_bbox, align_comp_to_port def cascode_common_source_netlist( pdk: MappedPDK, @@ -132,14 +132,15 @@ def cascode_common_source( if place_devices in ['vertical', 'V']: M2_ref.movey(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) - - top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") - top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") # Routing and Port definitions if place_devices in ['lateral', 'horizontal', 'H']: top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) + + # ************* Adding the suffix after the routing generates the prefix after routing. + top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") + top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") #Now attach pin names for port # text_pin_labels = list() # met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) @@ -147,12 +148,61 @@ def cascode_common_source( # pin_w_label = met5pin.copy() # pin_w_label.add_label(text=name,layer=(72,5),magnification=4) # text_pin_labels.append(pin_w_label) - - top_level.add_port('VIN', port=fet_M1.ports["multiplier_0_gate_W"]) - top_level.add_port('VBIAS', port=fet_M2.ports["multiplier_0_gate_W"]) - top_level.add_port('VSS', port=fet_M1.ports["multiplier_0_source_S"]) - top_level.add_port('IOUT', port=fet_M2.ports["multiplier_0_drain_N"]) + # print(f"Getting port list of top level",top_level.get_ports_list) + # print(top_level.ports) + # print(top_level.pprint_ports()) + # print(M1_ref.pprint_ports()) + # ************** Adding ports through component instances fails LVS. ** + top_level.add_port('VIN', port=M1_ref.ports['multiplier_0_gate_W']) + top_level.add_port('VBIAS', port=M2_ref.ports["multiplier_0_gate_W"]) + top_level.add_port('VSS', port=M1_ref.ports["multiplier_0_source_S"]) + top_level.add_port('IOUT', port=M2_ref.ports["multiplier_0_drain_N"]) + # ************** Adding ports through top_level fails LVS.Crates duplicate ports in addition to declared ports. ************** + # top_level.add_port('VIN', port=top_level.ports['M1_gate_W']) + # top_level.add_port('VBIAS', port=top_level.ports['M2_gate_W']) + # top_level.add_port('VSS', port=top_level.ports['M1_source_S']) + # top_level.add_port('IOUT', port=top_level.ports['M1_drain_N']) + # print(top_level.pprint_ports()) + # text_pin_labels = list() + # met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) + top_level.unlock() + move_info =list() + met1_pin=(68,20) + met1_label=(68,5) + met2_pin = (69,16) + met2_label = (69,5) + met3_pin = (70,16) + met3_label = (70,5) + met4_pin = (71,16) + met4_label = (71,5) + met5_pin = (72,16) + met5_label = (72,5) + VIN_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + VIN_label.add_label(text="VIN", layer=met1_label) + move_info.append((VIN_label, M1_ref.ports['multiplier_0_gate_W'], None)) + + VBIAS_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + VBIAS_label.add_label(text="VBIAS", layer=met1_label) + move_info.append((VBIAS_label, M2_ref.ports['multiplier_0_gate_W'], None)) + + VSS_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + VSS_label.add_label(text="VSS", layer=met1_label) + move_info.append((VSS_label, M1_ref.ports['multiplier_0_source_S'], None)) + + IOUT_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + IOUT_label.add_label(text="IOUT", layer=met1_label) + move_info.append((IOUT_label, M2_ref.ports['multiplier_0_drain_N'], None)) + + for comp, prt, alignment in move_info: + alignment = ('c','b') if alignment is None else alignment + compref = align_comp_to_port(comp, prt, alignment=alignment) + top_level.add(compref) + + print(top_level.pprint_ports()) + # pin_w_label = met5pin.copy() + # pin_w_label.add_label(text=name,layer=(72,5),magnification=4) + # text_pin_labels.append(pin_w_label) top_level.info['netlist'] = cascode_common_source_netlist( pdk, @@ -179,7 +229,7 @@ def cascode_common_source( else: print("DRC failed. Please try again.") -Cascode_cs_component.name = 'cascode_common_source_lvs' -netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') -print(f"LVS results", netgen_lvs_result) +# Cascode_cs_component.name = 'cascode_common_source_lvs' +# netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') +# print(f"LVS results", netgen_lvs_result) From c0bbccd5400fd8a628b4f1a8009ec8fdc8a6e5a6 Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Fri, 4 Oct 2024 07:29:16 +0000 Subject: [PATCH 14/17] Adding ports --- .../cascode_common_source.py | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 7fd376d17..dd5813bb6 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -142,21 +142,11 @@ def cascode_common_source( top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") #Now attach pin names for port - # text_pin_labels = list() - # met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) - # for name in ['VIN', 'VBIAS', 'VSS', 'IOUT']: - # pin_w_label = met5pin.copy() - # pin_w_label.add_label(text=name,layer=(72,5),magnification=4) - # text_pin_labels.append(pin_w_label) - # print(f"Getting port list of top level",top_level.get_ports_list) - # print(top_level.ports) - # print(top_level.pprint_ports()) - # print(M1_ref.pprint_ports()) - # ************** Adding ports through component instances fails LVS. ** - top_level.add_port('VIN', port=M1_ref.ports['multiplier_0_gate_W']) - top_level.add_port('VBIAS', port=M2_ref.ports["multiplier_0_gate_W"]) - top_level.add_port('VSS', port=M1_ref.ports["multiplier_0_source_S"]) - top_level.add_port('IOUT', port=M2_ref.ports["multiplier_0_drain_N"]) + # ************** Adding port labels through component instances fails LVS. ** + # top_level.add_port('VIN', port=M1_ref.ports['multiplier_0_gate_W']) + # top_level.add_port('VBIAS', port=M2_ref.ports["multiplier_0_gate_W"]) + # top_level.add_port('VSS', port=M1_ref.ports["multiplier_0_source_S"]) + # top_level.add_port('IOUT', port=M2_ref.ports["multiplier_0_drain_N"]) # ************** Adding ports through top_level fails LVS.Crates duplicate ports in addition to declared ports. ************** # top_level.add_port('VIN', port=top_level.ports['M1_gate_W']) # top_level.add_port('VBIAS', port=top_level.ports['M2_gate_W']) @@ -179,19 +169,23 @@ def cascode_common_source( met5_label = (72,5) VIN_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() VIN_label.add_label(text="VIN", layer=met1_label) - move_info.append((VIN_label, M1_ref.ports['multiplier_0_gate_W'], None)) + # move_info.append((VIN_label, M1_ref.ports['multiplier_0_gate_W'], None)) + move_info.append((VIN_label, top_level.ports['M1_gate_W'], None)) VBIAS_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() VBIAS_label.add_label(text="VBIAS", layer=met1_label) - move_info.append((VBIAS_label, M2_ref.ports['multiplier_0_gate_W'], None)) + # move_info.append((VBIAS_label, M2_ref.ports['multiplier_0_gate_W'], None)) + move_info.append((VBIAS_label, top_level.ports['M2_gate_W'], None)) VSS_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() VSS_label.add_label(text="VSS", layer=met1_label) - move_info.append((VSS_label, M1_ref.ports['multiplier_0_source_S'], None)) + # move_info.append((VSS_label, M1_ref.ports['multiplier_0_source_S'], None)) + move_info.append((VSS_label, top_level.ports['M1_source_S'], None)) IOUT_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() IOUT_label.add_label(text="IOUT", layer=met1_label) - move_info.append((IOUT_label, M2_ref.ports['multiplier_0_drain_N'], None)) + # move_info.append((IOUT_label, M2_ref.ports['multiplier_0_drain_N'], None)) + move_info.append((IOUT_label, top_level.ports['M2_drain_N'], None)) for comp, prt, alignment in move_info: alignment = ('c','b') if alignment is None else alignment From e8bb0b4f539e911798584b42c27b88adb306f2be Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Wed, 9 Oct 2024 22:56:32 +0000 Subject: [PATCH 15/17] Updated the netlist function. --- .../cascode_common_source.py | 39 +++++-------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index dd5813bb6..8fa57693c 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -128,9 +128,9 @@ def cascode_common_source( M2_ref_centre_coord = prec_ref_center(fet_M2) place_devices='V' if place_devices in ['lateral', 'horizontal', 'H']: - M2_ref.movex(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) + M2_ref.movex(0.75*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) if place_devices in ['vertical', 'V']: - M2_ref.movey(0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) + M2_ref.movey(0.75*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1])) # Routing and Port definitions if place_devices in ['lateral', 'horizontal', 'H']: @@ -142,20 +142,8 @@ def cascode_common_source( top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") #Now attach pin names for port - # ************** Adding port labels through component instances fails LVS. ** - # top_level.add_port('VIN', port=M1_ref.ports['multiplier_0_gate_W']) - # top_level.add_port('VBIAS', port=M2_ref.ports["multiplier_0_gate_W"]) - # top_level.add_port('VSS', port=M1_ref.ports["multiplier_0_source_S"]) - # top_level.add_port('IOUT', port=M2_ref.ports["multiplier_0_drain_N"]) - # ************** Adding ports through top_level fails LVS.Crates duplicate ports in addition to declared ports. ************** - # top_level.add_port('VIN', port=top_level.ports['M1_gate_W']) - # top_level.add_port('VBIAS', port=top_level.ports['M2_gate_W']) - # top_level.add_port('VSS', port=top_level.ports['M1_source_S']) - # top_level.add_port('IOUT', port=top_level.ports['M1_drain_N']) - # print(top_level.pprint_ports()) - # text_pin_labels = list() - # met5pin = rectangle(size=(5,5),layer=(72,16), centered=True) top_level.unlock() + # *** Adding pins and labels for metal1-5 *** move_info =list() met1_pin=(68,20) met1_label=(68,5) @@ -167,24 +155,21 @@ def cascode_common_source( met4_label = (71,5) met5_pin = (72,16) met5_label = (72,5) - VIN_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + port_size = (0.5,0.5) + VIN_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() VIN_label.add_label(text="VIN", layer=met1_label) - # move_info.append((VIN_label, M1_ref.ports['multiplier_0_gate_W'], None)) move_info.append((VIN_label, top_level.ports['M1_gate_W'], None)) - VBIAS_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + VBIAS_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() VBIAS_label.add_label(text="VBIAS", layer=met1_label) - # move_info.append((VBIAS_label, M2_ref.ports['multiplier_0_gate_W'], None)) move_info.append((VBIAS_label, top_level.ports['M2_gate_W'], None)) - VSS_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + VSS_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() VSS_label.add_label(text="VSS", layer=met1_label) - # move_info.append((VSS_label, M1_ref.ports['multiplier_0_source_S'], None)) move_info.append((VSS_label, top_level.ports['M1_source_S'], None)) - IOUT_label=rectangle(layer=met1_pin, size=(1,1), centered=True).copy() + IOUT_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() IOUT_label.add_label(text="IOUT", layer=met1_label) - # move_info.append((IOUT_label, M2_ref.ports['multiplier_0_drain_N'], None)) move_info.append((IOUT_label, top_level.ports['M2_drain_N'], None)) for comp, prt, alignment in move_info: @@ -193,10 +178,6 @@ def cascode_common_source( top_level.add(compref) print(top_level.pprint_ports()) - - # pin_w_label = met5pin.copy() - # pin_w_label.add_label(text=name,layer=(72,5),magnification=4) - # text_pin_labels.append(pin_w_label) top_level.info['netlist'] = cascode_common_source_netlist( pdk, @@ -223,7 +204,7 @@ def cascode_common_source( else: print("DRC failed. Please try again.") -# Cascode_cs_component.name = 'cascode_common_source_lvs' -# netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') +Cascode_cs_component.name = 'cascode_common_source_lvs' +netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') # print(f"LVS results", netgen_lvs_result) From 460b30301e80f8edf76b652aaaa8e83e671b153a Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Wed, 9 Oct 2024 23:17:51 +0000 Subject: [PATCH 16/17] Port size reduced. --- .../cascode_common_source.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 8fa57693c..9e86cdb39 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -20,7 +20,11 @@ def cascode_common_source_netlist( length: float, multipliers: int, n_or_p_fet: Optional[str] = 'nfet', - subckt_only: Optional[bool] = False + subckt_only: Optional[bool] = False, + m1_fingers = int, + m2_fingers = int, + m1_multipliers = int, + m2_multipliers = int ) -> Netlist: if length is None: length = pdk.get_grule('poly')['min_width'] @@ -137,6 +141,7 @@ def cascode_common_source( top_level << straight_route(pdk, M1_ref.ports["multiplier_0_drain_W"], M2_ref.ports["multiplier_0_source_E"]) if place_devices in ['vertical', 'V']: top_level << c_route(pdk, M1_ref.ports["multiplier_0_drain_E"], M2_ref.ports["multiplier_0_source_E"]) + # ************* Adding the suffix after the routing generates the prefix after routing. top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") @@ -155,7 +160,7 @@ def cascode_common_source( met4_label = (71,5) met5_pin = (72,16) met5_label = (72,5) - port_size = (0.5,0.5) + port_size = (0.35,0.35) VIN_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() VIN_label.add_label(text="VIN", layer=met1_label) move_info.append((VIN_label, top_level.ports['M1_gate_W'], None)) @@ -177,15 +182,20 @@ def cascode_common_source( compref = align_comp_to_port(comp, prt, alignment=alignment) top_level.add(compref) - print(top_level.pprint_ports()) top_level.info['netlist'] = cascode_common_source_netlist( pdk, - width=kwargs.get('width', 3), length=kwargs.get('length', 1), multipliers=numcols, + width=kwargs.get('width', 3), + length=kwargs.get('length', 1), + multipliers=numcols, n_or_p_fet=device, - subckt_only=True + subckt_only=True, + m1_fingers = m1_fingers, + m2_fingers = m2_fingers, + m1_multipliers = m1_multipliers, + m2_multipliers = m2_multipliers ) - + return top_level @@ -206,5 +216,5 @@ def cascode_common_source( Cascode_cs_component.name = 'cascode_common_source_lvs' netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') -# print(f"LVS results", netgen_lvs_result) + From 4fb49f953e3e566f87b9f33ab8336633bdf4a5fe Mon Sep 17 00:00:00 2001 From: Sudhansu Mishra Date: Sun, 10 Nov 2024 10:00:19 +0000 Subject: [PATCH 17/17] Port labelling added. --- .../cascode_common_source.py | 170 +++++++++++++++--- 1 file changed, 147 insertions(+), 23 deletions(-) diff --git a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py index 9e86cdb39..9848d4dce 100644 --- a/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py +++ b/openfasoc/generators/glayout/glayout/flow/blocks/elementary/cascode_common_source/cascode_common_source.py @@ -14,10 +14,50 @@ from glayout.flow.pdk.util.comp_utils import prec_ref_center, prec_center, movey, evaluate_bbox, align_comp_to_port +# def cascode_common_source_netlist( +# pdk: MappedPDK, +# width: float, +# length: float, +# multipliers: int, +# n_or_p_fet: Optional[str] = 'nfet', +# subckt_only: Optional[bool] = False, +# m1_fingers = int, +# m2_fingers = int, +# m1_multipliers = int, +# m2_multipliers = int +# ) -> Netlist: +# if length is None: +# length = pdk.get_grule('poly')['min_width'] +# if width is None: +# width = 3 +# mtop = multipliers if subckt_only else 1 +# model = pdk.models[n_or_p_fet] + +# source_netlist = """.subckt {circuit_name} {nodes} """ + f'l={length} w={width} m={mtop} ' + """ +# XM1 INT VIN VSS VSS {model} l={{length}} w={{width}} m={{m1_multipliers}} +# XM2 IOUT VBIAS INT VSS {model} l={{length}} w={{width}} m={{m2_multipliers}}""" +# source_netlist += "\n.ends {circuit_name}" + +# instance_format = "X{name} {nodes} {circuit_name} l={length} w={width} m={mult}" + +# return Netlist( +# circuit_name='CASCODECOMMONSRC', +# nodes=['VIN', 'VBIAS', 'VSS', 'IOUT'], +# source_netlist=source_netlist, +# instance_format=instance_format, +# parameters={ +# 'model': model, +# 'width': width, +# 'length': length, +# 'mult': multipliers +# } +# ) def cascode_common_source_netlist( pdk: MappedPDK, - width: float, - length: float, + m1_width: float, + m2_width: float, + m1_length: float, + m2_length: float, multipliers: int, n_or_p_fet: Optional[str] = 'nfet', subckt_only: Optional[bool] = False, @@ -26,16 +66,22 @@ def cascode_common_source_netlist( m1_multipliers = int, m2_multipliers = int ) -> Netlist: - if length is None: - length = pdk.get_grule('poly')['min_width'] - if width is None: - width = 3 + if m1_length is None: + m1_length = pdk.get_grule('poly')['min_length'] + if m1_width is None: + m1_width = pdk.get_grule('poly')['min_width'] + m2_length = m2_length or pdk.get_grule('poly')['min_length'] + m2_width = m2_width or pdk.get_grule('poly')['min_width'] + mtop = multipliers if subckt_only else 1 model = pdk.models[n_or_p_fet] + m1_multipliers = m1_multipliers or 1 + m2_multipliers = m2_multipliers or 1 + - source_netlist = """.subckt {circuit_name} {nodes} """ + f'l={length} w={width} m={mtop} ' + """ -XM1 INT VIN VSS VSS {model} l={{l}} w={{w}} m={{m}} -XM2 IOUT VBIAS INT VSS {model} l={{l}} w={{w}} m={{m}}""" + source_netlist = """.subckt {circuit_name} {nodes} """ + f'l={m1_length} w={m1_width} m={mtop} ' + """ +XM1 INT VIN VSS VSS {model} l={m1_length} w={m1_width} m={m1_multipliers} +XM2 IOUT VBIAS INT VSS {model} l={m2_length} w={m2_width} m={m2_multipliers}""" source_netlist += "\n.ends {circuit_name}" instance_format = "X{name} {nodes} {circuit_name} l={length} w={width} m={mult}" @@ -47,13 +93,18 @@ def cascode_common_source_netlist( instance_format=instance_format, parameters={ 'model': model, - 'width': width, - 'length': length, - 'mult': multipliers + 'm1_width': m1_width, + 'm2_width': m2_width, + 'm1_length': m1_length, + 'm2_length': m2_length, + 'mult': multipliers, + 'm1_multipliers': m1_multipliers, + 'm2_multipliers': m2_multipliers, } ) + #@cell def cascode_common_source( pdk: MappedPDK, @@ -144,6 +195,7 @@ def cascode_common_source( # ************* Adding the suffix after the routing generates the prefix after routing. + top_level.unlock() top_level.add_ports(M1_ref.get_ports_list(), prefix="M1_") top_level.add_ports(M2_ref.get_ports_list(), prefix="M2_") #Now attach pin names for port @@ -182,23 +234,94 @@ def cascode_common_source( compref = align_comp_to_port(comp, prt, alignment=alignment) top_level.add(compref) - + top_level.flatten() + # THIS IS THE ORIGINAL ARGUMENTS FOR THE NETLIST GENERATION FUNCTION + # top_level.info['netlist'] = cascode_common_source_netlist( + # pdk, + # width=kwargs.get('width', 3), + # length=kwargs.get('length', 1), + # multipliers=numcols, + # n_or_p_fet=device, + # subckt_only=True, + # m1_fingers = m1_fingers, + # m2_fingers = m2_fingers, + # m1_multipliers = m1_multipliers, + # m2_multipliers = m2_multipliers + # ) top_level.info['netlist'] = cascode_common_source_netlist( pdk, - width=kwargs.get('width', 3), - length=kwargs.get('length', 1), - multipliers=numcols, + m1_width=kwargs.get('width', 21), + m2_width=kwargs.get('width', 21), + m1_length=kwargs.get('length',14), + m2_length=kwargs.get('length',14), + multipliers=16, n_or_p_fet=device, subckt_only=True, - m1_fingers = m1_fingers, - m2_fingers = m2_fingers, - m1_multipliers = m1_multipliers, - m2_multipliers = m2_multipliers + m1_fingers = 6, + m2_fingers = 6, + m1_multipliers = 9, + m2_multipliers = 9 ) - + + generated_netlist_for_lvs = top_level.info['netlist'].generate_netlist() + print(f"Type of generated netlist is :", generated_netlist_for_lvs) + file_path_local_storage = "./gen_netlist.txt" + try: + with open(file_path_local_storage, 'w') as file: + file.write(generated_netlist_for_lvs) + except: + print(f"Verify the file availability and type: ", generated_netlist_for_lvs, type(generated_netlist_for_lvs)) return top_level +def cascode_common_source_labels(CMS: Component) -> Component: + CMS.unlock() + + # ************* Adding the suffix after the routing generates the prefix after routing. + CMS.unlock() + CMS.add_ports(M1_ref.get_ports_list(), prefix="M1_") + CMS.add_ports(M2_ref.get_ports_list(), prefix="M2_") + #Now attach pin names for port + CMS.unlock() + # *** Adding pins and labels for metal1-5 *** + move_info =list() + met1_pin=(68,20) + met1_label=(68,5) + met2_pin = (69,16) + met2_label = (69,5) + met3_pin = (70,16) + met3_label = (70,5) + met4_pin = (71,16) + met4_label = (71,5) + met5_pin = (72,16) + met5_label = (72,5) + port_size = (0.35,0.35) + VIN_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() + VIN_label.add_label(text="VIN", layer=met1_label) + move_info.append((VIN_label, CMS.ports['M1_gate_W'], None)) + + VBIAS_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() + VBIAS_label.add_label(text="VBIAS", layer=met1_label) + move_info.append((VBIAS_label, CMS.ports['M2_gate_W'], None)) + + VSS_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() + VSS_label.add_label(text="VSS", layer=met1_label) + move_info.append((VSS_label, CMS.ports['M1_source_S'], None)) + + IOUT_label=rectangle(layer=met1_pin, size=port_size, centered=True).copy() + IOUT_label.add_label(text="IOUT", layer=met1_label) + move_info.append((IOUT_label, CMS.ports['M2_drain_N'], None)) + + for comp, prt, alignment in move_info: + alignment = ('c','b') if alignment is None else alignment + compref = align_comp_to_port(comp, prt, alignment=alignment) + CMS.add(compref) + + return CMS.flatten() + + + + mapped_pdk_build = sky130 Cascode_cs_component = cascode_common_source(mapped_pdk_build, m1_fingers=10, @@ -215,6 +338,7 @@ def cascode_common_source( print("DRC failed. Please try again.") Cascode_cs_component.name = 'cascode_common_source_lvs' -netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') - +# netgen_lvs_result = mapped_pdk_build.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') +sky130.lvs_netgen(Cascode_cs_component, 'cascode_common_source_lvs') +print('LVS success??')