From b2d67ea476a0440270c71427ac363add11670de6 Mon Sep 17 00:00:00 2001 From: labtob <70279295+alibillalhammoud@users.noreply.github.com> Date: Thu, 6 Jun 2024 00:05:50 -0400 Subject: [PATCH] cmirror fix pdk import --- docs/source/notebooks/glayout/GLayout_Cmirror.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/notebooks/glayout/GLayout_Cmirror.ipynb b/docs/source/notebooks/glayout/GLayout_Cmirror.ipynb index 7d67820d2..704bb80bd 100644 --- a/docs/source/notebooks/glayout/GLayout_Cmirror.ipynb +++ b/docs/source/notebooks/glayout/GLayout_Cmirror.ipynb @@ -1 +1 @@ -{"cells":[{"cell_type":"markdown","metadata":{"id":"aK2t7aSWNojQ"},"source":["# GLayout Current Mirror Tutorial\n"]},{"cell_type":"markdown","metadata":{"id":"view-in-github"},"source":["\"Open\n"]},{"cell_type":"markdown","metadata":{"id":"xjDewsT5Y4lP"},"source":["```\n","OpenFASOC Team, Feb 2024\n","SPDX-License-Identifier: Apache-2.0\n","```"]},{"cell_type":"markdown","metadata":{"id":"-Xp4cEjkeHIx"},"source":["## Introduction\n","Welcome!\n","This notebook serves as an introduction to the GDSFactory-based layout automation tool **GLayout** and an example producing a VIA to explain grules and glayers, as a part of [OpenFASoC](https://github.com/idea-fasoc/OpenFASOC). \n","\n","This Notebook will run as-is on Google Collab, or you can run locally by using the install steps in [this document](https://docs.google.com/document/d/e/2PACX-1vRL8ksIvB-fHaqWgkgBPDUznOcDmmFhNrvzPNx9GSSkZyfhJYexEI9gBZCJ0SNNnHdUrAf1EBOeU182/pub). If you choose a local install, skip part 1 of this notebook.\n"]},{"cell_type":"markdown","metadata":{"id":"j4dNshkgMM4I"},"source":["## Installation On Google Collab\n","### 1. Clone the repository and install dependencies\n","**Python Dependencies**\n","* [`gdsfactory`](https://github.com/gdsfactory/gdsfactory): Provides the backend for GDS manipulation.\n","* [`sky130`](https://github.com/gdsfactory/skywater130): The Skywater 130nm PDK Python package for GDSFactory to use in this demo.\n","* [`gf180`](https://github.com/gdsfactory/gf180): The GF 180nm PDK Python package for GDSFactory to use in this demo.\n","* [`gdstk`](https://heitzmann.github.io/gdstk/): (installed as a part of gdsfactory) Used for converting GDS files into SVG images for viewing.\n","* [`svgutils`](https://svgutils.readthedocs.io/en/latest/): To scale the SVG image.\n","\n","**System Dependencies**\n","* [`klayout`](https://klayout.de/): For DRC (Design Rule Checking).\n"]},{"cell_type":"markdown","metadata":{"id":"bANz_LDB8TQW"},"source":["#### 1.1. Installing the binary dependency `klayout` using micromamba\n","**You only need to run this once**"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"JzDjayJIMSHe","scrolled":true},"outputs":[],"source":["# Setup the environment for the OpenFASOC GDSFactory generator\n","# You only need to run this block once!\n","\n","# Clone OpenFASoC\n","!git clone https://github.com/idea-fasoc/OpenFASOC\n","# Install python dependencies\n","!pip install sky130\n","!pip install gf180 prettyprinttree svgutils\n","!pip install gdsfactory==7.7.0\n","\n","import pathlib\n","import os\n","# Install KLayout (via conda)\n","!curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba\n","conda_prefix_path = pathlib.Path('conda-env')\n","CONDA_PREFIX = str(conda_prefix_path.resolve())\n","%env CONDA_PREFIX={CONDA_PREFIX}\n","\n","!bin/micromamba create --yes --prefix $CONDA_PREFIX\n","# Install from the litex-hub channel\n","!bin/micromamba install --yes --prefix $CONDA_PREFIX \\\n"," --channel litex-hub \\\n"," --channel main \\\n"," klayout\n"]},{"cell_type":"markdown","metadata":{"id":"B6dO3W3m8TQZ"},"source":["#### 1.2. Adding the `klayout` binary to the system path, then goto the GLayout directory\n","**You need to run this each time you restart the kernel**"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Izl4QURo8TQa"},"outputs":[],"source":["# Setup the environment for the OpenFASOC GDSFactory generator\n","\n","# Adding micro-mamba binary directory to the PATH\n","# This directory contains Klayout\n","import pathlib\n","import os\n","conda_prefix_path = pathlib.Path('conda-env')\n","CONDA_PREFIX = str(conda_prefix_path.resolve())\n","%env CONDA_PREFIX={CONDA_PREFIX}\n","# Add conda packages to the PATH\n","PATH = os.environ['PATH']\n","%env PATH={PATH}:{CONDA_PREFIX}/bin\n","\n","%cd /content/OpenFASOC/openfasoc/generators/glayout"]},{"cell_type":"markdown","metadata":{"id":"e-sbwZb_8TQb"},"source":["#### 1.3. Importing Libraries and Utility Functions"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Nc7wGAz68TQb"},"outputs":[],"source":["from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130\n","from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk as gf180\n","import gdstk\n","import svgutils.transform as sg\n","import IPython.display\n","from IPython.display import clear_output\n","import ipywidgets as widgets\n","\n","# Redirect all outputs here\n","hide = widgets.Output()\n","\n","def display_gds(gds_file, scale = 3):\n"," # Generate an SVG image\n"," top_level_cell = gdstk.read_gds(gds_file).top_level()[0]\n"," top_level_cell.write_svg('out.svg')\n"," # Scale the image for displaying\n"," fig = sg.fromfile('out.svg')\n"," fig.set_size((str(float(fig.width) * scale), str(float(fig.height) * scale)))\n"," fig.save('out.svg')\n","\n"," # Display the image\n"," IPython.display.display(IPython.display.SVG('out.svg'))\n","\n","def display_component(component, scale = 3):\n"," # Save to a GDS file\n"," with hide:\n"," component.write_gds(\"out.gds\")\n"," display_gds('out.gds', scale)\n"]},{"cell_type":"markdown","metadata":{"id":"ywJ1Xc5K395z"},"source":["# Current Mirror Layout Design using GLayout API\n","\n","## Overview\n","\n","This document provides a detailed tutorial on using the GLayout API to design and generate a layout for a PMOS current mirror circuit. It outlines the steps to initialize the layout components, place the devices, make necessary adjustments, route the connections, and generate the final layout for visualization.\n","\n","## Prerequisites\n","\n","Ensure that you have the following installed:\n","- Python environment with access to GLayout API.\n","- GDSFactory package for handling generic layout components.\n","- A PDK (Process Design Kit) appropriate for the technology node you're working on (e.g., `gf180` in this example).\n","\n","## Step-by-Step Guide\n","\n","### Step 1: Setting up the Environment\n","\n","**1.1 Import Required Modules**\n","Begin by importing the necessary classes and functions from the GLayout and GDSFactory packages:\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"idb2xYtJqwna"},"outputs":[],"source":["from glayout.flow.primitives.guardring import tapring\n","from glayout.flow.primitives.fet import pmos\n","from glayout.flow.pdk.util.comp_utils import evaluate_bbox, prec_center\n","from glayout.flow.pdk.mappedpdk import MappedPDK\n","from glayout.flow.routing.straight_route import straight_route\n","from glayout.flow.routing.c_route import c_route\n","from gdsfactory import Component\n","from glayout.pdk.gf180_mapped import gf180_mapped_pdk"]},{"cell_type":"markdown","metadata":{"id":"fy1-h5NTq0US"},"source":["### Step 2: Define the Current Mirror Function\n","\n","**2.1 Initialize the Current Mirror Component**\n","Within your Python script, start by defining the `currentMirror` function that takes in a `MappedPDK` object:\n","```python\n","def currentMirror(pdk: MappedPDK):\n"," currMirrComp = Component()\n","```\n","\n","**2.2 Create the Transistor Instances**\n","Use the PDK to instantiate two PMOS transistors, a reference and a mirror, with specified modifications:\n","```python\n"," pfet_ref = pmos(with_substrate_tap=False, with_dummy=(False, True))\n"," pfet_mir = pmos(with_substrate_tap=False, with_dummy=(True, False))\n","```\n","\n","**2.3 Add Transistors to the Component**\n","Insert the transistors into the current mirror component and position them:\n","```python\n"," cref_ref = currMirrComp << pfet_ref\n"," cmir_ref = currMirrComp << pfet_mir\n"," cref_ref.movex(evaluate_bbox(pfet_mir)[0] + max_metal_separation(pdk))\n","```\n","\n","**2.4 Add and Position the Tap Ring**\n","Incorporate a tap ring and ensure it encloses the transistors with additional padding to satisfy design rules:\n","```python\n"," tap_ring = tapring(pdk, enclosed_rectangle=evaluate_bbox(currMirrComp.flatten(), padding=pdk.get_grule(\"nwell\", \"active_diff\")[\"min_enclosure\"]))\n"," shift_amount = -prec_center(currMirrComp.flatten())[0]\n"," tring_ref = currMirrComp << tap_ring\n"," tring_ref.movex(destination=shift_amount)\n","```\n","\n","**2.5 Route the Connections**\n","Create routes between the ports:\n","```python\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_source_E\"], cmir_ref.ports[\"multiplier_0_source_E\"])\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cmir_ref.ports[\"multiplier_0_gate_E\"])\n"," currMirrComp << c_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cref_ref.ports[\"multiplier_0_drain_E\"])\n","\n"," return currMirrComp\n","```\n","\n","### Step 3: Visualizing the Layout\n","\n","**3.1 Generate and View the Layout**\n","Finally, visualize the generated layout by calling the `currentMirror` function and using the `.show()` method:\n","```python\n","# To visualize the layout\n","currentMirror(gf180).show()\n","```"]},{"cell_type":"markdown","metadata":{"id":"EFtjsVAixzzr"},"source":["Create the final design cell with the following code block:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"DGCUq98Qx58n"},"outputs":[],"source":["def currentMirror(pdk: MappedPDK):\n"," currMirrComp = Component()\n"," pfet_ref = pmos(pdk, with_substrate_tap=False, with_dummy=(False, True))\n"," pfet_mir = pmos(pdk, with_substrate_tap=False, with_dummy=(True, False))\n"," cref_ref = currMirrComp << pfet_ref\n"," cmir_ref = currMirrComp << pfet_mir\n"," pdk.util_max_metal_seperation()\n"," cref_ref.movex(evaluate_bbox(pfet_mir)[0] + pdk.util_max_metal_seperation())\n"," tap_ring = tapring(pdk, enclosed_rectangle=evaluate_bbox(currMirrComp.flatten(), padding=pdk.get_grule(\"nwell\", \"active_diff\")[\"min_enclosure\"]))\n"," shift_amount = -prec_center(currMirrComp.flatten())[0]\n"," tring_ref = currMirrComp << tap_ring\n"," tring_ref.movex(destination=shift_amount)\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_source_E\"], cmir_ref.ports[\"multiplier_0_source_E\"])\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cmir_ref.ports[\"multiplier_0_gate_E\"])\n"," currMirrComp << c_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cref_ref.ports[\"multiplier_0_drain_E\"])\n"," return currMirrComp\n","\n","currentMirror(gf180_mapped_pdk).write_gds(\"cmirror_example.gds\")\n","display_gds(\"cmirror_example.gds\")"]},{"cell_type":"markdown","metadata":{"id":"gLC6QYRbxk-v"},"source":["## Conclusion\n","\n","Following these steps results in a PMOS current mirror layout being composed and visualized. The tap ring encloses the transistors and the routing utilities are used to create the required connections respecting the design rules specified by the PDK.\n","\n","Each function call and module used here directly corresponds to a specific structure or operation within the context of the PDK and the layout process. This example provides a foundation upon which more complex circuits can be designed using the powerful features of the GLayout API."]}],"metadata":{"colab":{"provenance":[]},"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.7"},"vscode":{"interpreter":{"hash":"397704579725e15f5c7cb49fe5f0341eb7531c82d19f2c29d197e8b64ab5776b"}}},"nbformat":4,"nbformat_minor":0} +{"cells":[{"cell_type":"markdown","metadata":{"id":"aK2t7aSWNojQ"},"source":["# GLayout Current Mirror Tutorial\n"]},{"cell_type":"markdown","metadata":{"id":"view-in-github"},"source":["\"Open\n"]},{"cell_type":"markdown","metadata":{"id":"xjDewsT5Y4lP"},"source":["```\n","OpenFASOC Team, Feb 2024\n","SPDX-License-Identifier: Apache-2.0\n","```"]},{"cell_type":"markdown","metadata":{"id":"-Xp4cEjkeHIx"},"source":["## Introduction\n","Welcome!\n","This notebook serves as an introduction to the GDSFactory-based layout automation tool **GLayout** and an example producing a VIA to explain grules and glayers, as a part of [OpenFASoC](https://github.com/idea-fasoc/OpenFASOC). \n","\n","This Notebook will run as-is on Google Collab, or you can run locally by using the install steps in [this document](https://docs.google.com/document/d/e/2PACX-1vRL8ksIvB-fHaqWgkgBPDUznOcDmmFhNrvzPNx9GSSkZyfhJYexEI9gBZCJ0SNNnHdUrAf1EBOeU182/pub). If you choose a local install, skip part 1 of this notebook.\n"]},{"cell_type":"markdown","metadata":{"id":"j4dNshkgMM4I"},"source":["## Installation On Google Collab\n","### 1. Clone the repository and install dependencies\n","**Python Dependencies**\n","* [`gdsfactory`](https://github.com/gdsfactory/gdsfactory): Provides the backend for GDS manipulation.\n","* [`sky130`](https://github.com/gdsfactory/skywater130): The Skywater 130nm PDK Python package for GDSFactory to use in this demo.\n","* [`gf180`](https://github.com/gdsfactory/gf180): The GF 180nm PDK Python package for GDSFactory to use in this demo.\n","* [`gdstk`](https://heitzmann.github.io/gdstk/): (installed as a part of gdsfactory) Used for converting GDS files into SVG images for viewing.\n","* [`svgutils`](https://svgutils.readthedocs.io/en/latest/): To scale the SVG image.\n","\n","**System Dependencies**\n","* [`klayout`](https://klayout.de/): For DRC (Design Rule Checking).\n"]},{"cell_type":"markdown","metadata":{"id":"bANz_LDB8TQW"},"source":["#### 1.1. Installing the binary dependency `klayout` using micromamba\n","**You only need to run this once**"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"JzDjayJIMSHe","scrolled":true},"outputs":[],"source":["# Setup the environment for the OpenFASOC GDSFactory generator\n","# You only need to run this block once!\n","\n","# Clone OpenFASoC\n","!git clone https://github.com/idea-fasoc/OpenFASOC\n","# Install python dependencies\n","!pip install sky130\n","!pip install gf180 prettyprinttree svgutils\n","!pip install gdsfactory==7.7.0\n","\n","import pathlib\n","import os\n","# Install KLayout (via conda)\n","!curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba\n","conda_prefix_path = pathlib.Path('conda-env')\n","CONDA_PREFIX = str(conda_prefix_path.resolve())\n","%env CONDA_PREFIX={CONDA_PREFIX}\n","\n","!bin/micromamba create --yes --prefix $CONDA_PREFIX\n","# Install from the litex-hub channel\n","!bin/micromamba install --yes --prefix $CONDA_PREFIX \\\n"," --channel litex-hub \\\n"," --channel main \\\n"," klayout\n"]},{"cell_type":"markdown","metadata":{"id":"B6dO3W3m8TQZ"},"source":["#### 1.2. Adding the `klayout` binary to the system path, then goto the GLayout directory\n","**You need to run this each time you restart the kernel**"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Izl4QURo8TQa"},"outputs":[],"source":["# Setup the environment for the OpenFASOC GDSFactory generator\n","\n","# Adding micro-mamba binary directory to the PATH\n","# This directory contains Klayout\n","import pathlib\n","import os\n","conda_prefix_path = pathlib.Path('conda-env')\n","CONDA_PREFIX = str(conda_prefix_path.resolve())\n","%env CONDA_PREFIX={CONDA_PREFIX}\n","# Add conda packages to the PATH\n","PATH = os.environ['PATH']\n","%env PATH={PATH}:{CONDA_PREFIX}/bin\n","\n","%cd /content/OpenFASOC/openfasoc/generators/glayout"]},{"cell_type":"markdown","metadata":{"id":"e-sbwZb_8TQb"},"source":["#### 1.3. Importing Libraries and Utility Functions"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Nc7wGAz68TQb"},"outputs":[],"source":["from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130\n","from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk as gf180\n","import gdstk\n","import svgutils.transform as sg\n","import IPython.display\n","from IPython.display import clear_output\n","import ipywidgets as widgets\n","\n","# Redirect all outputs here\n","hide = widgets.Output()\n","\n","def display_gds(gds_file, scale = 3):\n"," # Generate an SVG image\n"," top_level_cell = gdstk.read_gds(gds_file).top_level()[0]\n"," top_level_cell.write_svg('out.svg')\n"," # Scale the image for displaying\n"," fig = sg.fromfile('out.svg')\n"," fig.set_size((str(float(fig.width) * scale), str(float(fig.height) * scale)))\n"," fig.save('out.svg')\n","\n"," # Display the image\n"," IPython.display.display(IPython.display.SVG('out.svg'))\n","\n","def display_component(component, scale = 3):\n"," # Save to a GDS file\n"," with hide:\n"," component.write_gds(\"out.gds\")\n"," display_gds('out.gds', scale)\n"]},{"cell_type":"markdown","metadata":{"id":"ywJ1Xc5K395z"},"source":["# Current Mirror Layout Design using GLayout API\n","\n","## Overview\n","\n","This document provides a detailed tutorial on using the GLayout API to design and generate a layout for a PMOS current mirror circuit. It outlines the steps to initialize the layout components, place the devices, make necessary adjustments, route the connections, and generate the final layout for visualization.\n","\n","## Prerequisites\n","\n","Ensure that you have the following installed:\n","- Python environment with access to GLayout API.\n","- GDSFactory package for handling generic layout components.\n","- A PDK (Process Design Kit) appropriate for the technology node you're working on (e.g., `gf180` in this example).\n","\n","## Step-by-Step Guide\n","\n","### Step 1: Setting up the Environment\n","\n","**1.1 Import Required Modules**\n","Begin by importing the necessary classes and functions from the GLayout and GDSFactory packages:\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"idb2xYtJqwna"},"outputs":[],"source":["from glayout.flow.primitives.guardring import tapring\n","from glayout.flow.primitives.fet import pmos\n","from glayout.flow.pdk.util.comp_utils import evaluate_bbox, prec_center\n","from glayout.flow.pdk.mappedpdk import MappedPDK\n","from glayout.flow.routing.straight_route import straight_route\n","from glayout.flow.routing.c_route import c_route\n","from gdsfactory import Component\n","from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk"]},{"cell_type":"markdown","metadata":{"id":"fy1-h5NTq0US"},"source":["### Step 2: Define the Current Mirror Function\n","\n","**2.1 Initialize the Current Mirror Component**\n","Within your Python script, start by defining the `currentMirror` function that takes in a `MappedPDK` object:\n","```python\n","def currentMirror(pdk: MappedPDK):\n"," currMirrComp = Component()\n","```\n","\n","**2.2 Create the Transistor Instances**\n","Use the PDK to instantiate two PMOS transistors, a reference and a mirror, with specified modifications:\n","```python\n"," pfet_ref = pmos(with_substrate_tap=False, with_dummy=(False, True))\n"," pfet_mir = pmos(with_substrate_tap=False, with_dummy=(True, False))\n","```\n","\n","**2.3 Add Transistors to the Component**\n","Insert the transistors into the current mirror component and position them:\n","```python\n"," cref_ref = currMirrComp << pfet_ref\n"," cmir_ref = currMirrComp << pfet_mir\n"," cref_ref.movex(evaluate_bbox(pfet_mir)[0] + max_metal_separation(pdk))\n","```\n","\n","**2.4 Add and Position the Tap Ring**\n","Incorporate a tap ring and ensure it encloses the transistors with additional padding to satisfy design rules:\n","```python\n"," tap_ring = tapring(pdk, enclosed_rectangle=evaluate_bbox(currMirrComp.flatten(), padding=pdk.get_grule(\"nwell\", \"active_diff\")[\"min_enclosure\"]))\n"," shift_amount = -prec_center(currMirrComp.flatten())[0]\n"," tring_ref = currMirrComp << tap_ring\n"," tring_ref.movex(destination=shift_amount)\n","```\n","\n","**2.5 Route the Connections**\n","Create routes between the ports:\n","```python\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_source_E\"], cmir_ref.ports[\"multiplier_0_source_E\"])\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cmir_ref.ports[\"multiplier_0_gate_E\"])\n"," currMirrComp << c_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cref_ref.ports[\"multiplier_0_drain_E\"])\n","\n"," return currMirrComp\n","```\n","\n","### Step 3: Visualizing the Layout\n","\n","**3.1 Generate and View the Layout**\n","Finally, visualize the generated layout by calling the `currentMirror` function and using the `.show()` method:\n","```python\n","# To visualize the layout\n","currentMirror(gf180).show()\n","```"]},{"cell_type":"markdown","metadata":{"id":"EFtjsVAixzzr"},"source":["Create the final design cell with the following code block:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"DGCUq98Qx58n"},"outputs":[],"source":["def currentMirror(pdk: MappedPDK):\n"," currMirrComp = Component()\n"," pfet_ref = pmos(pdk, with_substrate_tap=False, with_dummy=(False, True))\n"," pfet_mir = pmos(pdk, with_substrate_tap=False, with_dummy=(True, False))\n"," cref_ref = currMirrComp << pfet_ref\n"," cmir_ref = currMirrComp << pfet_mir\n"," pdk.util_max_metal_seperation()\n"," cref_ref.movex(evaluate_bbox(pfet_mir)[0] + pdk.util_max_metal_seperation())\n"," tap_ring = tapring(pdk, enclosed_rectangle=evaluate_bbox(currMirrComp.flatten(), padding=pdk.get_grule(\"nwell\", \"active_diff\")[\"min_enclosure\"]))\n"," shift_amount = -prec_center(currMirrComp.flatten())[0]\n"," tring_ref = currMirrComp << tap_ring\n"," tring_ref.movex(destination=shift_amount)\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_source_E\"], cmir_ref.ports[\"multiplier_0_source_E\"])\n"," currMirrComp << straight_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cmir_ref.ports[\"multiplier_0_gate_E\"])\n"," currMirrComp << c_route(pdk, cref_ref.ports[\"multiplier_0_gate_E\"], cref_ref.ports[\"multiplier_0_drain_E\"])\n"," return currMirrComp\n","\n","currentMirror(gf180_mapped_pdk).write_gds(\"cmirror_example.gds\")\n","display_gds(\"cmirror_example.gds\")"]},{"cell_type":"markdown","metadata":{"id":"gLC6QYRbxk-v"},"source":["## Conclusion\n","\n","Following these steps results in a PMOS current mirror layout being composed and visualized. The tap ring encloses the transistors and the routing utilities are used to create the required connections respecting the design rules specified by the PDK.\n","\n","Each function call and module used here directly corresponds to a specific structure or operation within the context of the PDK and the layout process. This example provides a foundation upon which more complex circuits can be designed using the powerful features of the GLayout API."]}],"metadata":{"colab":{"provenance":[]},"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.7"},"vscode":{"interpreter":{"hash":"397704579725e15f5c7cb49fe5f0341eb7531c82d19f2c29d197e8b64ab5776b"}}},"nbformat":4,"nbformat_minor":0}