Migrating from the Chip API#

If you have a script that starts like this, you are using an API that no longer exists:

from siliconcompiler import Chip

chip = Chip('heartbeat')
chip.input('heartbeat.v')
chip.load_target('freepdk45_demo')
chip.run()

The Chip class was removed in v0.35.0 (October 2025) and replaced by a Design object plus a project object. This page maps the old names onto the new ones.

Note

This page is kept indefinitely, and deliberately spells out the old names in full. Years of tutorials, papers, forum answers and blog posts use the Chip API, search engines still surface documentation for releases that predate the change, and code assistants trained on all of it will happily write Chip('mydesign') today. If you arrived here from one of those, you are in the right place.

Parameter-level changes – keys added, renamed or removed inside the schema itself – are recorded separately in Schema Changes.

Why it changed#

Chip was one object holding two unrelated things: what you are building and how this particular build is configured. That made a design impossible to reuse – to build the same RTL for two processes, or reuse a block inside a larger chip, you rebuilt the object from scratch.

The replacement separates them:

  • A Design describes source code: files, grouped into filesets, with a top module and include paths. It says nothing about a process or a flow, so the same Design can be built many ways, and one design can depend on another.

  • A project describes one compilation of a design. Use the class that matches the job – ASIC, FPGA, Lint or Sim – which is what replaces the old option,mode flag. Each one brings the schema, constraints and metrics for its domain, so an ASIC carries the asic,* parameters that a Lint has no use for. Project is the base class they extend, and is not the one to write a build script against: it has no domain section, so an ASIC target applied to a bare Project fails with AttributeError.

The second change is that configuration moved from string keypaths to typed accessorsproject.option.set_remote(True) rather than chip.set('option', 'remote', True). Keypaths still work and are still the layer underneath; see Working with the Schema for when to use which.

The same script, before and after#

The old form, from the heartbeat example as it shipped in v0.34.3:

from siliconcompiler import Chip
from siliconcompiler.targets import freepdk45_demo

chip = Chip('heartbeat')
chip.register_source("heartbeat-example", __file__)
chip.input("heartbeat.v", package="heartbeat-example")
chip.input("heartbeat.sdc", package="heartbeat-example")
chip.use(freepdk45_demo)
chip.run()
chip.summary()
chip.show()

The same build today. It is pulled in from examples/heartbeat/heartbeat.py, so it is exercised by the test suite rather than transcribed here:

design = Design("heartbeat")

# Set the root directory for the design's source files.
design.set_dataroot("heartbeat", __file__)

# Configure the RTL (Verilog) source files.
design.set_topmodule("heartbeat", fileset="rtl")
design.add_file("heartbeat.v", dataroot="heartbeat", fileset="rtl")

# Configure the SDC (timing constraints) file.
design.add_file("heartbeat.sdc", dataroot="heartbeat", fileset="sdc")

# Create an ASIC project from the design configuration.
project = ASIC(design)

# Enable the necessary filesets for the compilation flow.
project.add_fileset(["rtl", "sdc"])

# Load the pre-defined target for the Skywater130 demo process.
skywater130_demo(project)

# Execute the compilation flow.
project.run()

# Print a summary of the results (timing, area, power, etc.).
project.summary()

# Display the final physical layout in a GDS viewer.
project.show()

Four differences to notice, because they account for most of the porting work:

  1. Two objects instead of one. Design for the sources, ASIC for the build.

  2. Files carry a fileset. input() guessed a file’s role from its extension; add_file() requires you to name it, and the project then selects which filesets to compile with add_fileset().

  3. The top module is explicit. It used to be inferred from the Chip name.

  4. A target is called, not “used”. skywater130_demo(project) instead of chip.use(...) or chip.load_target(...).

Objects and imports#

Removed

Use instead

Chip

Design for the sources, plus one of ASIC / FPGA / Lint / Sim for the build (Project is their base class, not a substitute for them)

ASICProject

ASIC

Library, LibrarySchema

Design. Since schema 0.54.0 a library is a design; StdCellLibrary adds the standard-cell specifics

Flow, FlowgraphSchema

Flowgraph

Schema (top-level export)

Nothing to import. A project is a schema – get, set, getkeys and write_manifest are methods on it

DesignSchema, PDKSchema, ASICSchema, MetricSchema, …

The …Schema suffix is gone from the public names: Design, PDK, Checklist, Task

SiliconCompilerError

Standard Python exceptions

Warning

FPGA still exists and means something different. It used to be the FPGA device class; it is now the FPGA project class. The device is FPGADevice. Old code reading FPGA('mydevice') needs FPGADevice('mydevice').

Setting up a design#

Old

New

Chip('mydesign')

Design('mydesign')

chip.set('design', 'top')

design.set_topmodule('top', fileset='rtl')

chip.top()

design.get_topmodule(fileset='rtl')

chip.input('f.v')

design.add_file('f.v', fileset='rtl') – the fileset is explicit rather than guessed from the extension

chip.output(...)

Outputs are produced by tasks, not declared on the design

chip.register_source('name', __file__)

design.set_dataroot('name', __file__)

package='name' keyword

dataroot='name'. The schema field was renamed in schema 0.52.0, along with the find_files and check_filepaths arguments

chip.add('option', 'idir', 'include')

design.add_idir('include', fileset='rtl')

chip.add('option', 'define', 'SYNTHESIS')

design.add_define('SYNTHESIS', fileset='rtl')

chip.import_flist('files.f')

design.read_fileset('files.f', fileset='rtl')

chip.clock('clk', period=1.0)

Removed with no direct equivalent – the datasheet pin timing parameters it wrote are gone. Define clocks in an SDC file and add it to an sdc fileset

chip.use(mylib) for a library

project.add_dep(mylib), or list its filesets through design.add_depfileset()

chip.swap_library(old, new)

project.add_alias(old_dep, old_fileset, new_dep, new_fileset)

Configuring and running#

Old

New

chip.use(freepdk45_demo)

freepdk45_demo(project) – targets are still plain functions, and are called with the project

chip.load_target('freepdk45_demo')

Import the target and call it. The string form, and the option,target parameter behind it, are both gone

chip.set('option', 'mode', 'asic')

Use the ASIC project class. option,mode was removed in schema 0.42.7

chip.set('option', 'remote', True)

project.option.set_remote(True)

chip.set('option', 'builddir', 'out')

project.option.set_builddir('out')

chip.set('option', 'jobname', 'run1')

project.option.set_jobname('run1')

chip.set('option', 'quiet', True)

project.option.set_quiet(True)

chip.set('option', 'to', 'syn')

project.option.add_to('syn'); likewise add_from and add_prune

chip.set('option', 'flow', 'asicflow')

project.set_flow(ASICFlow()), or let the target set it

chip.run(), chip.summary(), chip.show()

Unchanged – same names on the project

chip.check_manifest()

project.check_manifest(), but call it after run(): library dependencies are resolved during the run, so a pre-run call reports failures on a correct configuration

chip.dashboard()

The CLI dashboard now runs during run() automatically; disable it with project.option.set_nodashboard(True). For the web dashboard, use the sc-dashboard command

chip.check_checklist()

Checklist.check() – see Checklists and signoff

chip.create_cmdline()

Unchanged in name, now provided by CommandLineSchema on the project

chip.error('message')

Raise an exception, or log through project.logger

Reading results and paths#

Old

New

chip.get('metric', 'cellarea', step=…, index=…)

Unchanged, but read it from the object run() returns: job metrics are reset on the live project when a run completes

chip.getworkdir()

siliconcompiler.utils.paths.workdir(project, step=…, index=…)

chip.getbuilddir()

siliconcompiler.utils.paths.builddir(project)

chip.collect(), chip.archive()

siliconcompiler.utils.curation.collect(project) and archive(project)

chip.find_result(...), chip.snapshot()

Unchanged – same names on the project

chip.find_node_file(...)

project.find_result(...)

chip.hash_files(...), chip.check_filepaths()

Unchanged in name, now schema methods; hash_files takes dataroot where it took package

chip.help('option', 'remote')

Removed. Parameter help text is in the Schema Reference, or project.getdict()

<design>.cfg

<design>.pkg.json. Manifests have been JSON with a .pkg.json extension since well before the Chip removal; a .cfg path in a script or a sc-dashboard -cfg invocation is stale

Building flows, tools and libraries#

Module-style setup functions became classes. Old flows, tool tasks, PDKs and libraries were modules exposing a setup(chip) function plus a make_docs hook, discovered by import:

# old: siliconcompiler/flows/myflow.py
def make_docs(chip):
    return setup()

def setup(flowname='myflow'):
    flow = siliconcompiler.Flow(flowname)
    flow.node(flowname, 'import', parse)
    flow.node(flowname, 'syn', syn_asic)
    flow.edge(flowname, 'import', 'syn')
    return flow

Now each is a class, and make_docs is gone – the documentation is generated from the class and its docstring:

# new
from siliconcompiler import Flowgraph

class MyFlow(Flowgraph):
    '''One-line summary, which becomes the description in the docs.'''
    def __init__(self):
        super().__init__("myflow")
        self.node("elaborate", Elaborate())
        self.node("synthesis", ASICSynthesis())
        self.edge("elaborate", "synthesis")

The same shape applies elsewhere: a tool task subclasses Task instead of exposing setup(chip), pre_process(chip) and post_process(chip) module functions; a standard cell library subclasses StdCellLibrary; a PDK subclasses PDK. Nodes take a task instance rather than a module reference, and node()/edge() are methods on the flowgraph rather than on the chip.

Targets are the exception: they are still functions taking a project, because a target’s job is to configure one.

See the Development Guide for how to write each of these, and Where your module belongs before you decide which repository it goes in – that answer also changed.

The command line#

There is no sc command, and there never was one after v0.35.0. The entry points are sc-dashboard, sc-issue, sc-remote, sc-server, sc-show, sc-install and smake.

Old

New

sc heartbeat.v -target freepdk45_demo

Write a Python script – see the example above – or use smake with a make.py

sc -target asic_demo

python3 -m siliconcompiler.demos.asic_demo

sc -target asic_demo -remote

python3 -m siliconcompiler.demos.asic_demo -remote

Everything else – sc-show, sc-issue, sc-remote and the rest – kept its name and its arguments.

Still stuck?#

If a symbol is not listed here, two places are worth checking before asking: Schema Changes for anything that looks like a schema key, and the Python API for a method name. Failing that, ask in Discussions – and please say which version the old script targeted, because it tells us which era of the API to translate from.