Coverage for apio / scons / plugin_gowin.py: 100%
50 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-25 02:31 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-25 02:31 +0000
1# -*- coding: utf-8 -*-
2# -- This file is part of the Apio project
3# -- (C) 2016-2018 FPGAwars
4# -- Author Jesús Arroyo
5# -- License GPLv2
6# -- Derived from:
7# ---- Platformio project
8# ---- (C) 2014-2016 Ivan Kravets <me@ikravets.com>
9# ---- License Apache v2
11"""Apio scons plugin for the gowin architecture."""
13# pylint: disable=duplicate-code
15from pathlib import Path
16from SCons.Script import Builder
17from SCons.Builder import BuilderBase
18from apio.common.common_util import SRC_SUFFIXES
19from apio.scons.apio_env import ApioEnv
20from apio.scons.plugin_base import PluginBase, ArchPluginInfo
21from apio.scons.plugin_util import (
22 verilator_lint_action,
23 has_testbench_name,
24 announce_testbench_action,
25 source_files_issue_scanner_action,
26 iverilog_action,
27 basename,
28 make_verilator_config_builder,
29 get_define_flags,
30)
33class PluginGowin(PluginBase):
34 """Apio scons plugin for the ice40 architecture."""
36 def __init__(self, apio_env: ApioEnv):
37 # -- Call parent constructor.
38 super().__init__(apio_env)
40 # -- Cache values.
41 yosys_path = Path(apio_env.params.environment.yosys_path)
42 self.yosys_lib_dir = yosys_path / "gowin"
43 self.sim_lib_files = [yosys_path / "gowin" / "cells_sim.v"]
44 self.lint_lib_files = self.sim_lib_files
46 def plugin_info(self) -> ArchPluginInfo:
47 """Return plugin specific parameters."""
48 return ArchPluginInfo(
49 constrains_file_suffix=".cst",
50 pnr_file_suffix=".pnr.json",
51 bitstream_file_suffix=".fs",
52 clk_name_index=0,
53 )
55 # @overrides
56 def synth_builder(self) -> BuilderBase:
57 """Creates and returns the synth builder."""
59 # -- Keep short references.
60 apio_env = self.apio_env
61 params = apio_env.params
62 gowin_params = params.fpga_info.gowin_params
64 # -- The yosys synth builder.
65 return Builder(
66 action=(
67 'yosys -p "synth_gowin -top {0} {1} -json $TARGET {2}" '
68 "{3} -DSYNTHESIZE {4} $SOURCES"
69 ).format(
70 params.apio_env_params.top_module,
71 (
72 f"-family {gowin_params.yosys_family}"
73 if gowin_params.yosys_family
74 else ""
75 ),
76 " ".join(params.apio_env_params.yosys_extra_options),
77 "" if params.verbosity.all or params.verbosity.synth else "-q",
78 get_define_flags(apio_env),
79 ),
80 suffix=".json",
81 src_suffix=SRC_SUFFIXES,
82 source_scanner=self.verilog_src_scanner,
83 )
85 # @overrides
86 def pnr_builder(self) -> BuilderBase:
87 """Creates and returns the pnr builder."""
89 # -- Keep short references.
90 apio_env = self.apio_env
91 params = apio_env.params
92 gowin_params = params.fpga_info.gowin_params
94 # -- We use an emmiter to add to the builder a second output file.
95 def emitter(target, source, env):
96 _ = env # Unused
97 target.append(apio_env.target + ".pnr")
98 return target, source
100 # -- Create the builder.
101 return Builder(
102 action=(
103 "nextpnr-himbaechel --device {0} --json $SOURCE "
104 "--write $TARGET --report {1} {2} "
105 "--vopt cst={3} {4} {6} {5}"
106 ).format(
107 params.fpga_info.part_num,
108 apio_env.target + ".pnr",
109 (
110 f"--vopt family={gowin_params.nextpnr_family}"
111 if gowin_params.nextpnr_family
112 else ""
113 ),
114 self.constrain_file(),
115 "" if params.verbosity.all or params.verbosity.pnr else "-q",
116 "--gui" if params.nextpnr_gui else "",
117 " ".join(params.apio_env_params.nextpnr_extra_options),
118 ),
119 suffix=".pnr.json",
120 src_suffix=".json",
121 emitter=emitter,
122 )
124 # @overrides
125 def bitstream_builder(self) -> BuilderBase:
126 """Creates and returns the bitstream builder."""
128 return Builder(
129 action="gowin_pack -d {0} -o $TARGET $SOURCE".format(
130 self.apio_env.params.fpga_info.gowin_params.packer_device
131 ),
132 suffix=".fs",
133 src_suffix=".pnr.json",
134 )
136 # @overrides
137 def testbench_compile_builder(self) -> BuilderBase:
138 """Creates and returns the testbench compile builder."""
140 # -- Keep short references.
141 apio_env = self.apio_env
142 params = apio_env.params
144 # -- Sanity checks
145 assert apio_env.targeting_one_of("sim", "test")
146 assert params.target.HasField("sim") or params.target.HasField("test")
148 # -- We use a generator because we need a different action
149 # -- string for sim and test.
150 def action_generator(target, source, env, for_signature):
151 _ = (source, env, for_signature) # Unused
152 # Extract testbench name from target file name.
153 testbench_file = str(target[0])
154 assert has_testbench_name(testbench_file), testbench_file
155 testbench_name = basename(testbench_file)
157 # Construct the actions list.
158 action = [
159 # -- Print a testbench title.
160 announce_testbench_action(),
161 # -- Scan source files for issues.
162 source_files_issue_scanner_action(),
163 # -- Perform the actual test or sim compilation.
164 iverilog_action(
165 apio_env,
166 verbose=params.verbosity.all,
167 vcd_output_name=testbench_name,
168 is_interactive=apio_env.targeting_one_of("sim"),
169 lib_dirs=[self.yosys_lib_dir],
170 lib_files=self.sim_lib_files,
171 ),
172 ]
173 return action
175 # -- The testbench compiler builder.
176 return Builder(
177 # -- Dynamic action string generator.
178 generator=action_generator,
179 suffix=".out",
180 src_suffix=SRC_SUFFIXES,
181 source_scanner=self.verilog_src_scanner,
182 )
184 # @overrides
185 def lint_config_builder(self) -> BuilderBase:
186 """Creates and returns the lint config builder."""
188 # -- Sanity checks
189 assert self.apio_env.targeting_one_of("lint")
191 # -- Make the builder.
192 return make_verilator_config_builder(
193 self.yosys_lib_dir,
194 rules_to_supress=[
195 "SPECIFYIGN",
196 ],
197 )
199 # @overrides
200 def lint_builder(self) -> BuilderBase:
201 """Creates and returns the lint builder."""
203 return Builder(
204 action=verilator_lint_action(
205 self.apio_env,
206 lib_dirs=[self.yosys_lib_dir],
207 lib_files=self.lint_lib_files,
208 ),
209 src_suffix=SRC_SUFFIXES,
210 source_scanner=self.verilog_src_scanner,
211 )