Bringing Your Own Design#

The demo builds someone else’s design. This page is the next question: you have RTL of your own, and you want to compile it.

There are four things to tell SiliconCompiler, and nothing else is required to start.

1. Describe the design#

A Design is a top module plus the filesets holding its sources. Sources go in rtl; timing constraints go in sdc, separately, because they change with the technology and the RTL does not:

from siliconcompiler import Design

design = Design("mydesign")
design.set_dataroot("root", __file__)

with design.active_dataroot("root"), design.active_fileset("rtl"):
    design.set_topmodule("mydesign")
    design.add_file("mydesign.v")
    design.add_file("submodule.v")

with design.active_dataroot("root"), design.active_fileset("sdc"):
    design.add_file("mydesign.sdc")

Design.set_dataroot() with __file__ makes every path relative to the script, so the design still builds when someone clones it somewhere else. That is worth doing from the start – see dataroot for the other kinds, including sources fetched from a git repository at a pinned commit.

Parameters and defines belong to the fileset too:

design.set_param("WIDTH", "32", fileset="rtl")
design.add_define("SYNTHESIS", fileset="rtl")

2. Check it before you build#

assert design.check_filepaths()

Ten seconds here saves a failed run later; unresolvable paths are the most common first failure. Then lint it, which needs no tools at all and catches the next tier of problem:

from siliconcompiler import Lint
from siliconcompiler.flows.lintflow import LintFlow

project = Lint(design)
project.add_fileset("rtl")
project.set_flow(LintFlow())
project.run()

See Lint your RTL. Do not skip this: synthesis error messages are much worse than lint error messages.

3. Pick a technology#

A target bundles the PDK, the standard cell libraries and the tool setup. Start with an open one – you can change it later without touching the design:

from siliconcompiler import ASIC
from siliconcompiler.targets import freepdk45_demo

project = ASIC(design)
project.add_fileset("rtl")
project.add_fileset("sdc")

freepdk45_demo(project)

Target

Use when

freepdk45_demo

You want fast results and are not taping out. A fictional 45nm process, so timing numbers are indicative, not real.

skywater130_demo

You want an open PDK that real silicon has been made in. Slower.

asap7_demo

You want to see behaviour at an advanced node. Predictive, not manufacturable.

gf180_demo, ihp130_demo

Other open PDKs with real foundry paths.

Constraints your design will probably need:

project.constraint.area.set_dieoutline(500, 500, coremargin=10)

Without a die area the floorplanner picks one from a utilisation target, which is fine until you have macros – see Instantiating a hardened module.

4. Run it#

project.run()
project.summary()

The summary is the first thing to read, and When a run fails is the second.

Then what?#

The interesting part starts once it builds. Common next steps, in the order people usually need them:

You want to

Go to

Use RTL from another repository

Building Your Own SoC – dataroots pinned to a commit

Compose your design from another design

Building Your Own SoCadd_depfileset

Use an SRAM or another hard macro

Instantiating a hardened module

Try several settings and keep the best

Parallel Job Execution – index parallelism

Sweep a parameter and compare

Multi-Job Flows

Compile from VHDL, Bluespec, Chisel or Migen

Hardware design frontends

Target an FPGA instead

Build for an FPGA

Not install any EDA tools

Docker, or a remote run

See also

Example designs – a working script for nearly every row above, and How do I…? for the one-off questions that come up along the way.