how tedious is it to do manual layouts
GLayout helps in doing analog layout as a tradition flow of analog include as shown below in the figure which is a very tedious task as compared to digital layout which doesn't include much of a manual work and this gap is brigded through the this tool. Question is HOW?
-
What is we can generalize the design rules & layers.
-
What if we can generate the layout by tweaking the different parameters.
-
What if we can do hierarchical component design along with routing & placement.
This is where GLayout comes into play........
GLayout provides us with the MappedPDK
class which stores the technology specific rules/layers in python dictionaries providing the designers with the necessary layers
& layout rules
.
-
Each process has a number of layers which will be called as generic layer and these generic layers are mapped to actual process layers using the MappedPDK class.
-
As we can see from below table that a polysilicon being a generic layer is mapped to actual process layer using the tuple data type in python for different technologies.
pdk.get_glayers() is a method within a MappedPDK class which stores the association of different layer specific to different process which can be used to select the layers to draw the geometries.
Each foundary uses different GDS layer number for different process steps for example you can refer the below table
Each technology has a certain design rules which needs to be followed for our design to be tape-out ready and MappedPDK stores these rules for all the stack layers.
- pdk.get_grules() is a method which helps us in accessing the specific rule related to each different layers be it a common dimensional checks like spacing, extension, minimum_width etc, arguments for this method include the generic layers that we are working on and the rule we want to access.
Ports describe an edges of polygon, they include different attributes like width, center etc which will be used for the routing purposes.
To generate a specif macro with number of devices instantiated and connected with each other GLayout provides us with the three types of routes known as C route, Straight route & L route.
We will be using a python library called GDSFactory for handeling generic layout components & generating the layouts for integrated circuit and we will be saving it in GDSII format.
GLayout will be generating the DRC clean layout & SPICE netlist for any PDK, composed of two parts:
-
Generic PDK framework: Allows to describe any PDK in a standardize format defined by
MappedPDK
class. -
Circuit generators: A python function which takes
MappedPDK
as an argument allowing us to set different parameters to produce a DRC clean layout which can be written to a.gds
file & SPICE netlist for a circuit component.
A python library which is being used in entire process of designing integrated circuits layout and save it directly to GDSII format
It has a generic PDkK framework which helps in describing any PDK in a standardized format with the help of MappedPDK
class along with some optional layout parameters to produce DRC & LVS clean layout which can be used for extraction of pre-PEX SPICE netlist for simulating the circuit
Run the following command to uninstall all conflicting packages:
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
- Set up Docker's apt repository.
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
- To install the latest version, run:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- Verify that the Docker Engine installation is successful by running the hello-world image.
sudo docker run hello-world
- clone the OpenFASOC repository
git clone https://github.com/idea-fasoc/OpenFASOC.git
- Navigate to the docker folder
cd OpenFASOC/docker/conda
- Build and run the Docker container
#For Linux/WSL
sudo docker build -t openfasoc:glayout .
cd ../../
sudo docker run -v $(pwd):$(pwd) -w $(pwd) --name glayoutcontainer -it openfasoc:glayout
pip install -r requirements.txt
pip install gdstk prettyprint
for running graphical applications (such as klayout) in the docker container Open a terminal and run
#For Linux/WSL
xhost +Local:*
- Open the Docker Container (the following commands create a new container from the image)
#For Linux
sudo docker run -v $(pwd):$(pwd) -w $(pwd) -e DISPLAY -v /temp/.X11-unix:/tmp/.X11-unix --net=host -it --name glayoutcontainer openfasoc:glayout
#For WSL
docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /mnt/wslg:/mnt/wslg -v $(pwd):$(pwd) -w $(pwd) -e DISPLAY -e WAYLAND_DISPLAY -e XDG_RUNTIME_DIR -e PULSE_SERVER --name glayoutcontainer openfasoc:glayout
Miscellaneous Docker Commands -
-
To remove the container, run the command: docker container rm glayoutcontainer
-
To restart the container, run the command docker container restart glayoutcontainer
-
To execute a running container, first check its status by running
a. docker container ls -a
b. docker exec -it glayoutcontainer bash (if glayoutcontainer is running) (-it runs the container in interactive mode)
Note: ‘exit’ in a running docker container halts all running processes and stops. A graceful shutdown can be achieved by using docker stop glayoutcontainer
Once the install is complete, you can check your install by running the following command
# assuming you are in the OpenFASOC directory
cd openfasoc/generators/glayout
python3 test_glayout.py
If you get the following error then try the below mentioned commands
cd openfasoc/generators/glayout
python3.10 -m pip install "numpy2.0.0"
python3 test_glayout.py
This script will test if:
-
The python version meets requirements (3.10 or newer)
-
The conda packages have been installed
-
The PDKs sky130 or gf180 have been installed and are in their expected locations
-
Python packages have been properly installed
-
glayout is working as required. The script:
a. places an nmos component
b. runs a Layout-vs-Schematic check on it
-
Run your container using a previously described run command (Step 8 of Install with Docker)
-
Run KLayout by just typing
klayout
in the docker container -
Install KLive
a. Go to Tools -> Manage Packages -> Install New Packages -> Search
b. Search for KLive
c. Install the package that looks like this:
-
Once it's installed, on your host system. Type in
docker ps -a
. This will list all of your running containers. Copy the container ID of the most recently started one or the one you installed klive -
Enter the command
docker commit <container id> openfasoc:glayout
you can follow the following playlist to view practical implementation of installation here or the following document here for all the different platforms.
python <filename>
If you get the following error then try the below mentioned commands
python3.10 -m pip install "numpy2.0.0"
python <filename>
#Importing the mappedPDK class for sky130 & gf180 process
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130
from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk as gf180
#Using get_glayer() method
sky130_met1 = sky130.get_glayer("met1")
gf180_met1 = gf180.get_glayer("met1")
sky130_poly = sky130.get_glayer("poly")
gf180_poly = gf180.get_glayer("poly")
#printing tuple for met1 in respective process
print(f"sky130_met1:{sky130_met1}")
print(f"gf180_met1: {gf180_met1}")
print(f"sky130_poly: {sky130_poly}")
print(f"gf180_poly: {gf180_poly}")
#Minimum Width
#Importing the mappedPDK class for sky130 & gf180 process
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130
from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk as gf180
#Using the get_grule() method
min_width_via1 = sky130.get_grule('via1')["min_width"]
//it returns a dictonary of layout rules
#Printing the minimum width
print(f"minimmum width for via1 {min_width_via1}")
#Minimum Enclosure
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130
from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk as gf180
min_enc_met1 = sky130.get_grule('via1','met1')["min_enclosure"] //get_grule -- Returns a dictionary describing the relationship between two layers
If one layer is specified, returns a dictionary with all intra layer rules
min_enc_met2 = sky130.get_grule('via1','met2')["min_enclosure"]
print("sky130")
print(f"min enclosure met1 and via1: {min_enc_met1}")
print(f"min enclosure met2 and via1: {min_enc_met2}")
min_enc_met1 = gf180.get_grule('via1','met1')["min_enclosure"]
min_enc_met2 = gf180.get_grule('via1','met2')["min_enclosure"]
print("gf180")
print(f"min enclosure met1 and via1: {min_enc_met1}")
print(f"min enclosure met2 and via1: {min_enc_met2}")
#Minimum Spacing
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk as sky130
from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk as gf180
min_met1_spacing = sky130.get_grule('met1', 'met1')["min_separation"]
min_met1_spacing = gf180.get_grule('met1', 'met1')["min_separation"]
print("sky130")
print(f"min spacing between metal1: {min_met1_spacing}")
print("gf180")
print(f"min spacing between metal1: {min_met1_spacing}")
from glayout.flow.pdk.mappedpdk import MappedPDK
from gdsfactory import component
from gdsfactory.components import rectangle
//defining a top level component using the glayout "component" function which which includes the geometries that we want to generate in out layout.
def met1track(pdk: MappedPDK, lenght):
met1 = pdk.get_glayer("met1")
met1_width = pdk.get_grule('met1')["min_width"]
top_level = component(name="metal_track")
top_level << rectangle(size=(length, met1_width), layer=met1) //using stream insertion operator helps to add the object into the component --> look into rectangle function once syntax
return top_level
metalTrack = met1track(sky130,3)
metalTrack.write_gds('met1track.gds')
#To view the layout in klayout
metalTrack.show()
from glayout.flow.pdk.mappedpdk import MappedPDK
from gdsfactory import component
from gdsfactory.components import rectangle
from glayout.flow.pdk.util.comp_utils import evaluate_bbox
def adjacentmet1track(pdk: MappedPDK, length)
track1 = met1track(pdk, length)
track2 = met1track(pdk, length)
top_level = component(name="adjacent_metal_track")
track1_ref = top_level << track1
track2_ref = top_level << track2
width = evaluate_bbox(track1)[1] #getting dimension on the y-axis
track2_ref.movey(width + pdk.get_grule('met1','met1')['min_separation']
return top_level
adjmettrack = adjacentmet1track(sky130,3)
adjmettrack.show()
adjmettrack.write_gds('adjmettrack.gds')
You can find all the primitives that glayout provides with their source code here
from glayout.flow.primitive.fet import pmos
from glayout.flow.primitive.fet import nmos
def twotransistor(pdk)
nfet = nmos(pdk)
pfet = pmos(pdk)
top_level = component()
pfet_ref = top_level << pfet
nfet_ref = top_level << nfet
compsep = pdk.util_max_metal_separation() //returns the maximum of the min_seperation rule for all layers specfied
although the name of this function is util_max_metal_seperation, layers do not have to be metals
you can specify non metals by using metal_levels=list of glayers
if metal_levels is list of int, integers are converted to metal levels
if a single int is provided, all metals below and including that int level are considerd
by default this function returns the maximum metal seperation of metals1-5
nfet_ref.movex(compsep + evaluate_bbox(pfet)[0])
return top_level
twoadjtransistor = twotransisitor(sky130)
twoadjtransistor.write_gds(twatransisitor.gds)
twoadjtransistor.show()
Glayout provides with various placement techniques which you can view from here
creates a C shaped route between two Ports.
extends a route from edge1 until perpindicular with edge2, then places a via This depends on the orientation of edge1 and edge2 if edge1 has the same orientation as edge2, the generator will rotate edge2 180 degrees Will not modify edge1 or edge2
creates a L shaped route between two Ports.
Glayout provides with various placement techniques which you can view from here
These are the widely used analog design to make the circuit resistant to variations by matching device characterstics
DRC - Checks the interaction of layout shapes
- Spacing
- Width
- Enclosure & Overlap
- Antenna
- Density
- Required layers
Damages to gate caused by charge buildup while etching --> Damage is cumulative --> Mitigated by mosfet drain connections, antenna diodes, or routing changes
Ensures the uniformity and avoid issues related to manufacturing variability --> maximum and minimum density --> overlapping grid based check: for sky130 700um x 700um window at 70um step --> minimum density generally not a problem because of fill --> minimum clear density = 1 - maximum density (77% maximum density = 23% minimum clear density)
LVS
- Extraction
- Layout patterns -> hierarchical text "netlist" of connected parameterized devices
- Comparison
- Netlists converted to graphs with devices/subcircuits as nodes and nets as edges
- Paraller/Series reduction
- Topology matching
- parameter check
- port check
Resistor reduction Mosfet reduction
Using pre-computed look-up table