Defining a Target#
A target in SiliconCompiler is a reusable “build configuration” for a specific type of project. Think of it as a master recipe that bundles together everything needed to compile a design for a particular goal, such as creating a low-power IoT chip on the Skywater 130nm process or a high-performance block on FreePDK45.
Targets are implemented as simple Python functions that configure a Project object. They are loaded by directly calling the function and passing in the project to configure, making it incredibly easy to set up a complex build.
A full list of built-in targets can be found on the targets page.
See also
Writing the module is only half the job – where it ships matters too. Open PDKs and standard cell libraries belong in lambdapdk, closed or proprietary ones in your own package (see Packaging an External Library), and tools, flows and targets in the SiliconCompiler repository itself. Where does my module go? walks through the choice.
Contributing the module back? CONTRIBUTING.md covers the pull request process, the four lint gates every PR is checked against, and how to build the docs.
Why Create a Target?#
While you can configure a project’s PDK, flow, and libraries manually, creating a target is the recommended approach for any serious project. The benefits include:
Encapsulation: It bundles all technology-specific and flow-specific settings into one place.
Reusability: The same target can be used across multiple designs, ensuring consistency.
Simplicity: It reduces a complex setup process to a single line of code in your build script.
Anatomy of a Target Function#
A target is a Python function that accepts a Project object as its first argument. Inside this function, you will typically perform the following actions:
Load Core Components: Set the fundamental building blocks of your compilation:
PDK: The process design kit for the manufacturing technology.
Flow: The sequence of EDA tool steps to run (e.g., synthesis, place-and-route).
Libraries: The standard cell libraries and/or macros to use. The primary one is the mainlib; the rest supplement it.
Set Default Constraints: Define the default goals and physical constraints for the design.
Timing Constraints: Clock speeds, I/O delays, and other performance goals.
Physical Constraints: Desired die area, core utilization (density), and pin placement.
Configure Tool Options: Set default options for specific tools in the flow, such as the number of cores to use for a given step.
Example: A Target for a Simple ASIC#
Let’s create a target for a generic ASIC design. This function will load a standard ASIC flow, a fictional PDK and library, and set some common physical and timing constraints.
from siliconcompiler import ASIC
from siliconcompiler.flows import asicflow
from siliconcompiler.tools.yosys import syn_asic
# It's common practice to import the PDK and library schemas
# that your target will use.
from my_designs.pdks import my_freepdk45
from my_designs.libs import my_nangate45
def my_asic_target(project: ASIC,
# Targets can be parameterized. Here, we allow the user
# to specify the number of cores for parallelizable steps.
place_np=1,
route_np=1):
'''
A simple target for a generic 45nm ASIC design.
'''
# 1. Load Core Components
# The order is important: load libraries and PDK first, then the flow.
project.set_mainlib(my_nangate45.Nangate45())
project.set_pdk(my_freepdk45.FreePDK45())
project.set_flow(asicflow.ASICFlow(place_np=place_np, route_np=route_np))
# 2. Set Default Constraints
# Timing Constraints: Define a "typical" corner for setup/hold analysis.
# This sets the performance goals for the design.
scenario = project.constraint.timing.make_scenario("typical")
scenario.add_libcorner("typical")
scenario.set_pexcorner("typical")
scenario.add_check(["setup", "hold"])
# Physical Constraints: Define the physical layout goals.
# Here, we aim for 40% core utilization and a 1-micron margin.
area = project.constraint.area
area.set_density(40)
area.set_coremargin(1)
# 3. Configure Tool Options
syn_asic.ASICSynthesis.find_task(project).set_strategy("AREA3")
How to Use the Target#
Once the target function is defined, you can load it into your project like this:
import siliconcompiler
# Create a project
project = siliconcompiler.ASIC()
# Load the entire configuration by calling the target function.
# We can also pass values for the parameterized arguments.
my_asic_target(project, place_np=4, route_np=4)
# Now the project is fully configured and ready to run!
# project.run()
Next Steps#
A target is composed of other SiliconCompiler modules. To build effective targets, you will need to understand how to define these components: