Now that all of the tools are installed, we can start working on the the actual process flow. The overall flow is described in The OpenLane Overview and describes the typical design sequence. Many of these steps are automated, though various steps may require additional inputs other than the outputs of their immediate predecessors.
Most tools are configured by adjusting environment variables, or by setting them in a config.tcl or config.json file. These tools also communicate by passing environment variables to child processes, and almost never pass project-specific settings on the command line.
Synthesis is the process of taking HDL and turning it into RTL. This step is most familiar to those who have used FPGAs in the past, as it uses much the same tooling.
The first step is to actually synthesize the RTL. This is done by setting a number of environment variables, then running yosys
and passing it the script synth.tcl. This performs synthesis and generates a netlist file according to the SAVE_NETLIST
environment variable.
yosys -c $OPENLANE_ROOT/scripts/yosys/synth.tcl
After the RTL is synthesized, it must be analysed to get a rough idea of what sort of timing we can expect from the finished product. Since we now know what sort of cells we have, this step can also tell us how much of the chip’s area is being used. Finally, we can also know which nets form the “critical path” where the worst offenders are.
OpenSTA is bundled as part of OpenROAD
, and is invoked using the sta.tcl script from OpenLane
:
openroad -exit $OPENLANE_ROOT/scripts/openroad/sta.tcl
Floorplanning is the process of dividing the rectangular chip area into multiple zones and populating those zones with components that were synthesized.
Floorplanning is done over the course of several steps, with each step refining the previous one. These steps will attempt to fit the design core area.
This step takes the RTL and places the cells in the specified area, ensuring that the cells all actually fit. It does this by dividing the area into rows and filling in components as it goes. This step also inserts any tie cell that is required.
This reads merged.nom.lef
and writes its output to the same file.
Note: It is currently unclear why this step is run twice.
openroad -exit $OPENLANE_ROOT/scripts/openroad/floorplan.tcl
openroad -exit $OPENLANE_ROOT/scripts/openroad/floorplan.tcl
Every cell that was added has input and output pins. For example, if the synthesized RTL contains an inverter, that inverter will have two pins.
The IO Placer step adds these pins to the design in random locations (?).
openroad -exit $OPENLANE_ROOT/scripts/openroad/ioplacer.tcl
The tapcell
step inserts welltap and endcap cells into the design as necessary.
Note
The log output uses the term decap here, but it seems as though it’s actually inserting endcap cells instead. Is this a typo?
openroad -exit $OPENLANE_ROOT/scripts/openroad/tapcell.tcl
The final floorplan step is to generate the power distribution network. This is accomplished with the pdngen
tool from openroad
.
This tool creates the power net for the chip. It is driven by evaluating pdn_cfg.tcl to define the networks prior to running pdn.tcl
openroad -exit $OPENLANE_ROOT/scripts/openroad/pdn.tcl
Placement is the process of selecting where to put elements in a design. There are two placement strategies available: Random, or RePlAce
. Random placement is fast but not very efficient, though is fine for simple designs.
The PL_RANDOM_GLB_PLACEMENT
setting in config.json
or config.tcl
can be set to true
to use random placement or false
to use RePlAce
.
This uses a Python script to randomly place cells in a design. For simple designs, this can be faster than using RePlAce
. It’s a very simple script and doesn’t get invoked using the normal TCL flow.
This command is aliased to global_placement
.
openroad -exit $OPENLANE_ROOT/scripts/openroad/gpl.tcl
The Placement Resizer performs several sub-steps, including estimating parasitics and running static timing analysis again.
The bulk of the step is detailed_placement
which shuffles cells that have just been placed in order to ensure they’re in legal positions.
If PL_RESIZER_DESIGN_OPTIMIZATIONS
is true, then the placement resizer step is run, otherwise it is skipped.
The next step is to synthesize the clock distribution network. If CLOCK_PORT
and CLOCK_NET
are not set, then this step is skipped.
This uses TritonCTS
, which is built into OpenROAD.
openroad -exit $OPENLANE_ROOT/scripts/openroad/cts.tcl
FastRoute - Performs global routing to generate a guide file for the detailed router
TritonRoute - Performs detailed routing
OpenRCX - Performs SPEF extraction
Magic - Streams out the final GDSII layout file from the routed def
KLayout - Streams out the final GDSII layout file from the routed def as a back-up
Magic - Performs DRC Checks & Antenna Checks
KLayout - Performs DRC Checks
Netgen - Performs LVS Checks
CVC - Performs Circuit Validity Checks
You can tie everything together by running flow.tcl
from OpenLane
:
PYTHONPATH=$VIRTUAL_ENV/lib/python3.10/site-packages/ \
STD_CELL_LIBRARY_OPT=sky130_fd_sc_hd \
STD_CELL_LIBRARY=sky130_fd_sc_hd \
PDK_ROOT=/opt/Si/PDKs/share/pdk \
PDK=sky130B \
./flow.tcl \
-design /opt/Si/work/inverter/ \
-ignore_mismatches
You can adjust settings by modifying your config.json
or config.tcl
file.
There are two important variables that affect routing density and fanout:
FP_CORE_UTIL
PL_TARGET_DENSITY
As a general rule of thumb, set the PL_TARGET_DENSITY
to 5% less than FP_CORE_UTIL
.
You will need to modify the user_defines.v
file in order to set the default GPIO pinmux settings. Without modifying these, the pins will be initialized in an indeterminate state.