| # Copyright 2023 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| |
| import("//build_overrides/pigweed.gni") |
| |
| import("$dir_pw_build/exec.gni") |
| |
| # Builds an FPGA image using the icestorm toolchain. |
| # |
| # Requires the following tools: |
| # yosys, nextpnr-ice40, icepack, icetime |
| # |
| # Example: |
| # |
| # fpga_image("toplevel") { |
| # sources = [ |
| # "gonk/csa_ctl_top.v", |
| # "gonk/pll.v", |
| # "gonk/rst_sync.v", |
| # "gonk/sig_sync.v", |
| # "gonk/spi_m_core.v", |
| # "gonk/spi_m_core_ctl.v", |
| # "gonk/spi_s_core.v", |
| # "gonk/top.v", |
| # ] |
| # |
| # pcf = "gonk/top.pcf" |
| # } |
| # |
| template("fpga_image") { |
| assert(defined(invoker.sources), "fpga_image requires 'sources'") |
| assert(defined(invoker.pcf), "fpga_image requires a 'pcf'") |
| |
| # Image basename set to target_name by default but can be overriden. |
| _image_name = "$target_name" |
| if (defined(invoker.image_name)) { |
| _image_name = invoker.image_name |
| } |
| |
| _verilog_files = invoker.sources |
| _pcf_file = invoker.pcf |
| |
| _json_file = "$target_out_dir/$target_name/${_image_name}.json" |
| _asc_file = "$target_out_dir/$target_name/${_image_name}.asc" |
| _bin_file = "$target_out_dir/$target_name/${_image_name}.bin" |
| |
| _yosys_log = "$target_out_dir/$target_name/yosys-log.txt" |
| _nextpnr_log = "$target_out_dir/$target_name/nextpnr-log.txt" |
| _timing_report_text = |
| "$target_out_dir/$target_name/${_image_name}_timing_report.txt" |
| _timing_report_json = |
| "$target_out_dir/$target_name/${_image_name}_timing_report.json" |
| |
| # By default, build the bin file and timing report. |
| group("$target_name") { |
| public_deps = [ |
| ":${target_name}._bin", |
| ":${target_name}._time", |
| ] |
| } |
| |
| pw_exec("${target_name}._json") { |
| inputs = [ _pcf_file ] + _verilog_files |
| outputs = [ |
| _json_file, |
| _yosys_log, |
| ] |
| |
| program = "yosys" |
| args = [ |
| "-l", |
| rebase_path(_yosys_log, root_build_dir), |
| "-q", |
| "-p", |
| "synth_ice40 -json " + rebase_path(_json_file, root_build_dir), |
| ] |
| args += rebase_path(_verilog_files, root_build_dir) |
| } |
| |
| pw_exec("${target_name}._asc") { |
| inputs = [ _json_file ] |
| outputs = [ |
| _asc_file, |
| _nextpnr_log, |
| ] |
| |
| deps = [ ":${invoker.target_name}._json" ] |
| |
| program = "nextpnr-ice40" |
| args = [ |
| "-l", |
| rebase_path(_nextpnr_log, root_build_dir), |
| "--freq", |
| "75", |
| "--hx8k", |
| "--package", |
| "tq144:4k", |
| "--json", |
| rebase_path(_json_file, root_build_dir), |
| "--pcf", |
| rebase_path(_pcf_file, root_build_dir), |
| "--asc", |
| rebase_path(_asc_file, root_build_dir), |
| "--opt-timing", |
| "--placer", |
| "heap", |
| ] |
| } |
| |
| pw_exec("${target_name}._bin") { |
| inputs = [ _asc_file ] |
| outputs = [ _bin_file ] |
| |
| deps = [ ":${invoker.target_name}._asc" ] |
| |
| program = "icepack" |
| args = [ |
| rebase_path(_asc_file, root_build_dir), |
| rebase_path(_bin_file, root_build_dir), |
| ] |
| } |
| |
| pw_exec("${target_name}._time") { |
| inputs = [ _asc_file ] |
| outputs = [ |
| _timing_report_text, |
| _timing_report_json, |
| ] |
| |
| deps = [ ":${invoker.target_name}._asc" ] |
| |
| program = "icetime" |
| args = [ |
| "-r", |
| rebase_path(_timing_report_text, root_build_dir), |
| "-j", |
| rebase_path(_timing_report_json, root_build_dir), |
| "-tmd", |
| "hx8k", |
| rebase_path(_asc_file, root_build_dir), |
| ] |
| } |
| } |