FPGA build flow

Tsfpga enables a build flow where many builds can be executed in parallel from the same script call. Any module can set up build projects using its module_*.py. All project configuration is located in the module, not in any central script.

The build project is represented using a Python class that abstracts all settings and operations.

Minimal build_fpga.py example

Given that we follow the folder structure, and have and least one module that sets up build projects, we can utilize a build_fpga.py like this:

Minimal build_fpga.py file.
from pathlib import Path
from tsfpga.build_project_list import BuildProjectList
from tsfpga.module import get_modules

modules = get_modules(modules_folder=Path("path/to/my/modules"))

build_path = Path("generated/my_build_projects")

projects = BuildProjectList(modules=modules, project_filters="*")
projects.create_unless_exists(project_paths=build_path, num_parallel_builds=4)
projects.build(project_path=build_path, num_parallel_builds=4, num_threads_per_build=6)

Of course this is incredibly simplified and hard coded, but it does show the interface to the tsfpga classes. The BuildProjectList class will work on a list of build project objects as supplied by the modules.

An example output from this script is shown below. It shows the build projects being launched in parallel, and then finishing at roughly the same time.

[/home/lukas/work/repo/tsfpga]$ python tsfpga/examples/build_fpga.py
Starting artyz7
Output file: /home/lukas/work/repo/tsfpga/generated/projects/artyz7/output.txt
Starting artyz7_dummy
Output file: /home/lukas/work/repo/tsfpga/generated/projects/artyz7_dummy/output.txt
pass (pass=1 fail=0 total=2) artyz7_dummy (229.5 seconds)

pass (pass=2 fail=0 total=2) artyz7 (229.8 seconds)

==== Summary ========================

Size of artyz7_dummy after implementation:
{
  "Total LUTs": 804,
  "Logic LUTs": 746,
  "LUTRAMs": 58,
  "SRLs": 0,
  "FFs": 1596,
  "RAMB36": 0,
  "RAMB18": 1,
  "DSP Blocks": 0
}
pass artyz7_dummy   (229.5 seconds)


Size of artyz7 after implementation:
{
  "Total LUTs": 804,
  "Logic LUTs": 746,
  "LUTRAMs": 58,
  "SRLs": 0,
  "FFs": 1596,
  "RAMB36": 0,
  "RAMB18": 1,
  "DSP Blocks": 0
}
pass artyz7         (229.8 seconds)

=====================================
pass 2 of 2
=====================================
Total time was 459.3 seconds
Elapsed time was 229.8 seconds
=====================================
All passed!

Note that before a project is built a register generation is run, so that the project is built using up-to-date register definitions.

Of course a more realistic build_fpga.py would be a little more verbose. It would probably feature command line arguments that control the behavior, output paths, etc. And example of this, which also features release artifact packaging, is available in the repo.

Example project class creation

This is an example of project creation, using the artyz7 example project from the repo.

Projects are created by modules using the file module_<module_name>.py, see folder structure for details. In tsfpga a top-level module that defines build projects is handled just like any other module. It can use register generation, set up simulations, etc. The only difference is that it overrides the BaseModule.get_build_projects() method to return a list of build project objects.

Example project creation
 1# Standard libraries
 2from pathlib import Path
 3
 4# First party libraries
 5from tsfpga.constraint import Constraint
 6from tsfpga.examples.example_env import get_hdl_modules, get_tsfpga_example_modules
 7from tsfpga.examples.vivado.project import TsfpgaExampleVivadoProject
 8from tsfpga.module import BaseModule
 9
10THIS_FILE = Path(__file__)
11
12
13class Module(BaseModule):
14    def get_build_projects(self):
15        projects = []
16
17        modules = get_hdl_modules() + get_tsfpga_example_modules()
18        part = "xc7z020clg400-1"
19
20        tcl_dir = self.path / "tcl"
21        pinning = Constraint(tcl_dir / "artyz7_pinning.tcl")
22        block_design = tcl_dir / "block_design.tcl"
23
24        projects.append(
25            TsfpgaExampleVivadoProject(
26                name="artyz7",
27                modules=modules,
28                part=part,
29                tcl_sources=[block_design],
30                constraints=[pinning],
31                defined_at=THIS_FILE,
32            )
33        )
34
35        projects.append(
36            TsfpgaExampleVivadoProject(
37                name="artyz7_explore",
38                top="artyz7_top",
39                modules=modules,
40                part=part,
41                tcl_sources=[block_design],
42                constraints=[pinning],
43                impl_explore=True,
44                defined_at=THIS_FILE,
45            )
46        )
47
48        projects.append(
49            TsfpgaExampleVivadoProject(
50                name="artyz7_verilog",
51                top="artyz7_top_verilog",
52                modules=modules,
53                part=part,
54                constraints=[pinning],
55                defined_at=THIS_FILE,
56            )
57        )
58
59        projects.append(
60            TsfpgaExampleVivadoProject(
61                name="artyz7_systemverilog",
62                top="artyz7_top_systemverilog",
63                modules=modules,
64                part=part,
65                constraints=[pinning],
66                defined_at=THIS_FILE,
67            )
68        )
69
70        return projects

There is a lot going on here, so lets go through what happens in get_build_projects().

Line 17: Get modules

Firstly we need to get a list of modules that shall be included in the build project. Source files, IP cores, scoped constraints, etc., from all these modules will be added to the project.

It can be a good idea to filter what modules are included here. If we have a huge module tree but our project only uses a subset of the modules, we might not want to slow down Vivado by adding everything. We might also use primitives and IP cores in some modules that are not available for the target part. This filtering of modules can be achieved using the arguments to get_modules().

In this case we use two wrappers, get_hdl_modules() and get_tsfpga_example_modules(), around the get_modules() function. They set the correct flags (modules paths, default registers and library_name_has_lib_suffix). It is recommended to use functions like these so the arguments don’t have to be repeated in many places.

Line 20-22: TCL files

This module has a sub-folder tcl which contains pinning and a block design. The block design, which is added to the VivadoProject as a TCL source is simply represented using it’s path. The pinning on the other hand, which is used as a constraint in Vivado, must be represented using the Constraint class.

Line 24-68: Creating project objects

The sources gathered are then use to create project objects that are appended to the projects list, which is returned at the end of the method.

First a VivadoProject object is created with the name artyz7. The modules, part name, TCL sources and constraints are passed to the constructor. There is also a defined_at argument, which is given the path to the module_artyz7.py file. This is used to get a useful --list result in our build_fpga.py.

The first project does not have the top argument set, which means it will be inferred from the provided name. After the first project, a few other projects are set up with different top levels and different settings. This is where we could also set different generics for the projects via the VivadoProject.__init__() constructor.

Note that all of these projects use a project subclass that inherits VivadoProject. In this case, the project subclass only adds a few more TCL sources with some further message severity settings. But using the project subclass concept we could do some more advanced things, for example setting up build hooks, as decsribed below.

Pre- and post- build function hooks

The VivadoProject functions pre_build() and post_build() can be convenient in certain use cases. They will receive all the arguments that are passed to VivadoProject.build(), such as project path, output path, etc. Additional named arguments sent to VivadoProject.build() will also be available in pre_build() and post_build().

Build result with utilization numbers

The VivadoProject.build() method will return a build_result.BuildResult object upon completion. It can be inspected to see if the run passed or failed, and what the resource utilization of the build is.

Example generated TCL

The TCL files below are generated by the VivadoProject class when calling the VivadoProject.create() and VivadoProject.build() methods as part of a build flow.

Create Vivado project

Click to expand/collapse code.
Example generated TCL that creates a Vivado project.
 1create_project -part "xc7z020clg400-1" "artyz7" {/home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/projects/artyz7}
 2set_property "target_language" "VHDL" [current_project]
 3
 4config_ip_cache -use_cache_location {/home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/vivado_ip_cache}
 5
 6
 7# ------------------------------------------------------------------------------
 8read_vhdl -library "axi_lite" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_cdc.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_to_axi_lite.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_simple_write_crossbar.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_simple_read_crossbar.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_mux.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_to_axi_lite_vec.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_to_vec.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_pipeline.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/src/axi_lite_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_lite/rtl/axi_lite_mux_netlist_build_wrapper.vhd}}
 9read_vhdl -library "reg_file" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/reg_file/src/axi_lite_reg_file.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/reg_file/src/interrupt_register.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/reg_file/src/reg_file_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/reg_file/rtl/axi_lite_reg_file_netlist_wrapper.vhd}}
10read_vhdl -library "axi" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_simple_read_crossbar.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_r_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_simple_write_crossbar.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_b_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_address_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_read_throttle.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_read_pipeline.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_w_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_write_cdc.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_write_pipeline.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_read_cdc.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi/src/axi_write_throttle.vhd}}
11read_vhdl -library "hard_fifo" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/hard_fifo/src/asynchronous_hard_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/hard_fifo/src/hard_fifo_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/hard_fifo/src/fifo36e2_wrapper.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/hard_fifo/src/hard_fifo.vhd}}
12read_vhdl -library "axi_stream" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/axi_stream/src/axi_stream_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/axi_stream/src/axi_stream_pkg.vhd}}
13read_vhdl -library "lfsr" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/lfsr/src/lfsr_fibonacci_single.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/lfsr/src/lfsr_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/lfsr/src/lfsr_fibonacci_multi.vhd}}
14read_vhdl -library "math" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/math/src/unsigned_divider.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/math/src/math_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/math/src/saturate_signed.vhd}}
15read_vhdl -library "fifo" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/fifo/src/fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/fifo/src/asynchronous_fifo.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/fifo/src/fifo_wrapper.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/fifo/rtl/fifo_netlist_build_wrapper.vhd}}
16read_vhdl -library "simple_dma" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/simple_dma/src/simple_dma_core.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/simple_dma/src/simple_dma_axi_lite.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/simple_dma/regs_src/simple_dma_register_record_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/simple_dma/regs_src/simple_dma_regs_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/simple_dma/regs_src/simple_dma_reg_file.vhd}}
17read_vhdl -library "common" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/common/src/common_context.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/handshake_merger.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/debounce.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/addr_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/handshake_pipeline.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/clock_counter.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/keep_remover.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/axi_stream_protocol_checker.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/handshake_splitter.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/width_conversion_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/types_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/width_conversion.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/clean_packet_dropper.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/common_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/handshake_mux.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/attribute_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/time_pkg.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/periodic_pulser.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/src/strobe_on_last.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/common/rtl/test_frequency_conversion.vhd}}
18read_vhdl -library "resync" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_level_on_signal.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_cycles.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_counter.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_level.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_slv_level.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_slv_level_on_signal.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_pulse.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_twophase_handshake.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/resync/src/resync_twophase.vhd}}
19read_vhdl -library "ring_buffer" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/ring_buffer/src/simple_ring_buffer_manager.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/ring_buffer/src/simple_ring_buffer_manager_pkg.vhd}}
20read_vhdl -library "sine_generator" -vhdl2008 {{/home/runner/work/hdl-modules/hdl-modules/modules/sine_generator/src/sine_lookup.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/sine_generator/src/sine_generator.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/sine_generator/src/sine_calculator.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/sine_generator/src/taylor_expansion_core.vhd} {/home/runner/work/hdl-modules/hdl-modules/modules/sine_generator/src/sine_generator_pkg.vhd}}
21read_vhdl -library "ddr_buffer" -vhdl2008 {{/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/ddr_buffer/src/ddr_buffer_top.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/ddr_buffer/regs_src/ddr_buffer_register_record_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/ddr_buffer/regs_src/ddr_buffer_regs_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/ddr_buffer/regs_src/ddr_buffer_reg_file.vhd}}
22read_vhdl -library "multiplication_ip" -vhdl2008 {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/multiplication_ip/src/multiplication.vhd}
23read_vhdl -library "artyz7" -vhdl2008 {{/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/resync_test.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/block_design_wrapper_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/block_design_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/mmcm_wrapper.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/block_design_wrapper.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/regs_src/artyz7_register_record_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/regs_src/artyz7_regs_pkg.vhd} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/regs_src/artyz7_reg_file.vhd}}
24read_verilog {{/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top_verilog_header.vh} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top_verilog.v}}
25read_verilog -sv {{/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top_systemverilog.sv} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top_systemverilog_header.svh} {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/src/artyz7_top_systemverilog_pkg.sv}}
26
27
28# ------------------------------------------------------------------------------
29source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/vivado/tcl/vivado_default_run.tcl}
30source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/vivado/tcl/vivado_fast_run.tcl}
31source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/vivado/tcl/vivado_messages.tcl}
32source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/tcl/block_design.tcl}
33source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/vivado/tcl/example_vivado_messages.tcl}
34source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/vivado/tcl/example_vivado_message_undriven_pin.tcl}
35
36
37# ------------------------------------------------------------------------------
38read_xdc -ref "asynchronous_fifo" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/fifo/scoped_constraints/asynchronous_fifo.tcl}
39set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/fifo/scoped_constraints/asynchronous_fifo.tcl}]
40read_xdc -ref "resync_level" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_level.tcl}
41set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_level.tcl}]
42read_xdc -ref "resync_counter" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_counter.tcl}
43set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_counter.tcl}]
44read_xdc -ref "resync_level_on_signal" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_level_on_signal.tcl}
45set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_level_on_signal.tcl}]
46read_xdc -ref "resync_pulse" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_pulse.tcl}
47set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_pulse.tcl}]
48read_xdc -ref "resync_twophase" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_twophase.tcl}
49set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_twophase.tcl}]
50read_xdc -ref "resync_twophase_handshake" -unmanaged {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_twophase_handshake.tcl}
51set_property "PROCESSING_ORDER" "LATE" [get_files {/home/runner/work/hdl-modules/hdl-modules/modules/resync/scoped_constraints/resync_twophase_handshake.tcl}]
52read_xdc -unmanaged {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/tcl/artyz7_pinning.tcl}
53set_property "PROCESSING_ORDER" "NORMAL" [get_files {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/artyz7/tcl/artyz7_pinning.tcl}]
54
55
56# ------------------------------------------------------------------------------
57add_files -fileset "utils_1" -norecurse {/home/runner/work/tsfpga/tsfpga/tsfpga/vivado/tcl/check_no_error_messages.tcl}
58foreach run [get_runs "synth_*"] {
59  set_property "STEPS.SYNTH_DESIGN.TCL.POST" {/home/runner/work/tsfpga/tsfpga/tsfpga/vivado/tcl/check_no_error_messages.tcl} ${run}
60}
61add_files -fileset "utils_1" -norecurse {/home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/projects/artyz7/hook_STEPS_WRITE_BITSTREAM_TCL_PRE.tcl}
62foreach run [get_runs "impl_*"] {
63  set_property "STEPS.WRITE_BITSTREAM.TCL.PRE" {/home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/projects/artyz7/hook_STEPS_WRITE_BITSTREAM_TCL_PRE.tcl} ${run}
64}
65
66
67# ------------------------------------------------------------------------------
68proc create_ip_core_fifo_generator_0 {} {
69  source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/multiplication_ip/ip_cores/fifo_generator_0.tcl}
70}
71create_ip_core_fifo_generator_0
72
73proc create_ip_core_mult_u12_u5 {} {
74  source -notrace {/home/runner/work/tsfpga/tsfpga/tsfpga/examples/modules/multiplication_ip/ip_cores/mult_u12_u5.tcl}
75}
76create_ip_core_mult_u12_u5
77
78
79# ------------------------------------------------------------------------------
80set_param "general.maxThreads" 7
81foreach run [get_runs "synth_*"] {
82  set_property "STEPS.SYNTH_DESIGN.ARGS.ASSERT" true ${run}
83}
84foreach run [get_runs "impl_*"] {
85  set_property "STEPS.WRITE_BITSTREAM.ARGS.BIN_FILE" true ${run}
86}
87
88
89# ------------------------------------------------------------------------------
90current_run [get_runs "synth_1"]
91set_property "top" "artyz7_top" [current_fileset]
92reorder_files -auto -disable_unused
93
94
95# ------------------------------------------------------------------------------
96exit

Build Vivado project

Click to expand/collapse code.
Example generated TCL that builds a Vivado project.
  1open_project {/home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/projects/artyz7/artyz7.xpr}
  2set_param "general.maxThreads" 12
  3set_param "synth.maxThreads" 8
  4
  5
  6# ------------------------------------------------------------------------------
  7set run [get_runs "synth_1"]
  8reset_run ${run}
  9launch_runs ${run} -jobs 12
 10
 11wait_on_run ${run}
 12
 13if {[get_property "PROGRESS" ${run}] != "100%"} {
 14  puts "ERROR: Run ${run} failed."
 15  exit 1
 16}
 17
 18
 19# ------------------------------------------------------------------------------
 20open_run ${run}
 21set run_directory [get_property "DIRECTORY" ${run}]
 22set should_exit 0
 23
 24
 25# ------------------------------------------------------------------------------
 26# Generate report on simultaneous switching noise (SSN) for the design.
 27# It seems safe to do this after synthesis; inspecting the reports in a test build after both
 28# synthesis and implementation shows that the results are identical.
 29# Will generate a "Designutils 20-923" message if noise margins are not met.
 30# If the user would like this to fail the build, this message severity shall be raised to ERROR.
 31# At the moment we do not know how stable this mechanism is, so we do not fail the build
 32# per default.
 33# The call is very fast (< 1s) so it is fine to run always, even though not everyone will use it.
 34set current_part [get_property "PART" [current_project]]
 35set part_supports_ssn [get_parts ${current_part} -filter {ssn_report == 1}]
 36if {${part_supports_ssn} != ""} {
 37    set output_file [file join ${run_directory} "report_ssn.html"]
 38    report_ssn -phase -format html -file ${output_file}
 39}
 40
 41
 42# ------------------------------------------------------------------------------
 43# This call is duplicated in 'report_utilization.tcl' for implementation.
 44set output_file [file join ${run_directory} "hierarchical_utilization.rpt"]
 45report_utilization -hierarchical -hierarchical_depth 4 -file ${output_file}
 46
 47
 48# ------------------------------------------------------------------------------
 49# This code is duplicated in 'check_timing.tcl' for implementation.
 50set clock_interaction_report [
 51  report_clock_interaction -delay_type "min_max" -no_header -return_string
 52]
 53if {[string first "(unsafe)" ${clock_interaction_report}] != -1} {
 54  puts "ERROR: Unhandled clock crossing in ${run} run. See 'clock_interaction.rpt' and 'timing_summary.rpt' in ${run_directory}."
 55
 56  set output_file [file join ${run_directory} "clock_interaction.rpt"]
 57  report_clock_interaction -delay_type min_max -file ${output_file}
 58
 59  set output_file [file join ${run_directory} "timing_summary.rpt"]
 60  report_timing_summary -file ${output_file}
 61
 62  set should_exit 1
 63}
 64
 65
 66# ------------------------------------------------------------------------------
 67# This code is duplicated in 'check_cdc.tcl' for implementation.
 68# Check that there are no critical CDC rule violations in the design.
 69# List of CDC rules: https://docs.amd.com/r/en-US/ug906-vivado-design-analysis/CDC-Rules-Precedence
 70# If this makes your build fail on a false positive, you can waive the rule using the
 71# 'create_waiver' command in a (scoped) constraint file.
 72# Rules can be disable in general (not recommended), or for specific paths using the '-from'
 73# and '-to' flags (recommended).
 74set cdc_report [report_cdc -return_string -no_header -details -severity "Critical"]
 75if {[string first "Critical" ${cdc_report}] != -1} {
 76  set output_file [file join ${run_directory} "cdc.rpt"]
 77  puts "ERROR: Critical CDC rule violation in ${run} run. See ${output_file}."
 78
 79  report_cdc -details -file ${output_file}
 80
 81  set should_exit 1
 82}
 83
 84
 85# ------------------------------------------------------------------------------
 86if {${should_exit} eq 1} {
 87  exit 1
 88}
 89
 90
 91# ------------------------------------------------------------------------------
 92set run [get_runs "impl_1"]
 93reset_run ${run}
 94launch_runs ${run} -jobs 12 -to_step "write_bitstream"
 95
 96wait_on_run ${run}
 97
 98if {[get_property "PROGRESS" ${run}] != "100%"} {
 99  puts "ERROR: Run ${run} failed."
100  exit 1
101}
102
103
104# ------------------------------------------------------------------------------
105puts "Creating hardware platform /home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/projects/artyz7/artyz7.xsa..."
106write_hw_platform -fixed -force -quiet -include_bit {/home/runner/work/tsfpga/tsfpga/generated/sphinx_rst/projects/artyz7/artyz7.xsa}
107
108
109# ------------------------------------------------------------------------------
110exit