Preparing the Silicon Compiler Run Script
Developing a Silicon Compiler run script for RTL-to-bitstream flow execution follows the same fundamental approach as developing a script for any Silicon Compiler flow execution. Additional resources for understanding Silicon Compiler fundamentals are available at docs.siliconcompiler.com
For most designs, the example Silicon Compiler run scripts provided with <tool_name> can be used as templates for creating your own. The commands used in these examples and the general method for constructing run scripts are described below.
Constructing a Silicon Compiler run script can be broken down into the following steps:
Import Modules
All Silicon Compiler run scripts are pure Python scripts that import Silicon Compiler functionality like any other Python module. Similarly, the <tool_name> RTL-to-bitstream flow is enabled as a set of Python modules that integrate to Silicon Compiler.
The minimum import requirements in a Logik Silicon Compiler run script are:
import siliconcompiler
from logik.targets import logik_target
Additional module imports may be required depending on project-specific requirements.
Create Main Function
Since the Silicon Compiler run script is just a Python script, executing it from the command line requires the same infrastructure as any other Python script. In most design flows, the most convenient way to enable this will be to simply encapsulate the script in a main() function:
In Python, an executable main() function is implemented with the following code:
def main(<main_function_parameters (optional)>):
#Insert your main function here
if __name__ == "__main__":
main()
Experienced Python programmers may prefer to use their own scripting methodology for executing the script instead of the above. Any approach that conforms to both Python and Silicon Compiler requirements should work.
Create Chip Object
Silicon Compiler design information is encapsulated in a Python class called Chip. An instance of this class is required for all Silicon Compiler run scripts and is commonly referred to as the chip object.
The Chip class constructor requires one parameter: the name of the top level module in your RTL design. A complete Chip instantiation takes the form
chip = siliconcompiler.Chip('<your_top_module_name>')
Nearly all components of a Silicon Compiler run script are calls to member functions of this class instance; it should be the first (or nearly the first) line in your main function.
Throughout this documentation, “chip” will be used to refer to the Chip class instance. However, there is no requirement that the instance be assigned to this variable name.
Select Part Name
Silicon Compiler associates each FPGA/eFPGA architecture with a unique ID called a part name.
Note
As of this writing, the only part name that is enabled for use is “logik_demo”
In your Silicon Compiler run script, include the following call
chip.set('fpga', 'partname', 'logik_demo')
to select the logik_demo part as your selected part name.
Register Packages (if needed)
Designs with dependencies on third-party or packaged IP from previous projects may require a method for importing design IP from a source other than local working directories. In Silicon Compiler, such imports are supported via the Silicon Compiler package registry, and the import process is referred to as registering a package.
Registering a package is enabled with a dedicated Chip class member function called register_package_source(). For complete details on this function, refer to Silicon Compiler’s documentation of the register_package_source() function.
An example use case for the package registry is shown below, outlining how to import a public Github repository so that its contents can be used as a package within Silicon Compiler. In this example, three parameters are provided to the register_package_source function: name, path, and ref. Name specifies a package name to be used when referring to the package elsewhere in code. Path specifies where Silicon Compiler can obtain the package; in this case, the package is obtained through Github. ref specifies to Silicon Compiler that the cloned Github repository should be checked out at a particular commit hash. Specifying ref is not necessary if the package is to be cloned from github on its main branch.
chip.register_package_source(
name='picorv32',
path='git+https://github.com/YosysHQ/picorv32.git',
ref='a7b56fc81ff1363d20fd0fb606752458cd810552')
Set Input Source Files
All HDL source files must be added to the Silicon Compiler chip object for inclusion. For each HDL file, include the following call in your Silicon Compiler run script
chip.input(<your_hdl_file_name>)
Support is provided for Verilog, VHDL and SystemVerilog inputs.
Note
Mixed-language flows are not yet supported. All HDL source files must be written in the same language.
When using VHDL, it is required to add
chip.set('option', 'frontend', 'vhdl')
to your run script to trigger Silicon Compiler to execute ghdl prior to running synthesis.
When using SystemVerilog, it is required to add
chip.set('option', 'frontend', 'systemverilog')
to your run script to trigger Silicon Compiler to execute sv2v prior to running synthesis.
When using Verilog, the default frontend option, Surelog, is used, and no function call is required to enable it.
Note
Silicon Compiler supports additional front end options, including flows for high-level synthesis. For all front end compilation considerations not described above, please consult Silicon Compiler Frontend documentation
For large designs, it may be convenient to organize your HDL files into a directory tree that is processed using Python functions, so that the above calls can be embedded in loops.
Adding Source Files From a Registered Package
When importing IP from a package in the Silicon Compiler package registry, the same function calls are used as described above, but it is also necessary to specify the package name. The call takes the form:
chip.input('<your_file_name>', package='<package_name>')
Set Timing Constraints
Note
The demo architecture provided with this distrbution implements a unit delay model. Provided examples demonstrate the RTL-to-bitstream flow without an SDC file. Examples that include SDC files are planned for a future release.
Timing constraints must be provided in a single SDC file. The SDC file must be added to the Silicon Compiler chip object for inclusion. Include the call
chip.add('input', 'constraint', 'sdc', '<your_sdc_file_name>')
in your Silicon Compiler run script.
Note
If no SDC file is provided, the flow will still run to completion. Timing analysis will be disabled during the place and route steps.
Set Pin Constraints
Pin constraints may be provided in one of two files:
A JSON pin constraints file (PCF)
A VPR XML placement constraints file
Note
If you need to specify placement constraints for design logic blocks in addition to specifying pin constraints, the XML placement constraints file must be used.
JSON Pin Constraint Specification
The JSON pin constraint file is unique to this flow. For additional information on creating the JSON pin constraint file, see Preparing Pin Constraints and Placement Constraints.
The JSON placement constraints file must be added to the Silicon Compiler chip object for inclusion. Include the call
chip.input('<your_pcf_file_name>')
If your project defines itself as a package using Silicon Compiler’s package registry, specify the package name as well:
chip.input('<your_pcf_file_name>', package=<your_package_name>)
in your Silicon Compiler run script
Note
The .pcf file extension must be used
VPR XML Placement Constraint Specification
VPR XML placement constraints are portable to any VPR-based place and route flow. For additional information on creating a VPR XML placement constraint file, see VPR’s documentation for placement constraints.
The XML placement constraints file must be added to the Silicon Compiler chip object for inclusion. Include the call
chip.add('input', 'constraint', 'pins', '<your_xml_file_name>')
in your Silicon Compiler run script.
Add Options
Numerous options can be added to your run script to control Silicon Compiler behavior or configure tools in the RTL-to-bitstream flow to behave as desired. For complete Silicon Compiler option specifications, refer to Silicon Compiler’s documentation for supported option settings.
In particular, any compiler directives that are required for HDL synthesis should be specified as Silicon Compiler options. These are furnished with Chip class member function calls of the form
chip.add('option', 'define', <compiler_directive>)
Configure Remote Execution (optional)
Silicon Compiler supports job submission to remote servers.
There are multiple ways to enable this execution model. Consult Silicon Compiler remote processing documentation for details.
Add Execution Calls
The final two lines of every run script should be the same:
chip.run()
chip.summary()
The run() call invokes the RTL-to-bitstream flow with all settings specified. The summary() call reports results of the run in tabular form. Included in the summary results are key design metrics such as FPGA resource utilization and tool execution runtimes.