Coverage for apio/commands/apio_sim.py: 100%
31 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-23 03:53 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-23 03:53 +0000
1# -*- coding: utf-8 -*-
2# -- This file is part of the Apio project
3# -- (C) 2016-2024 FPGAwars
4# -- Authors
5# -- * Jesús Arroyo (2016-2019)
6# -- * Juan Gonzalez (obijuan) (2019-2024)
7# -- License GPLv2
8"""Implementation of 'apio sim' command"""
10import sys
11from pathlib import Path
12import click
13from apio.common.apio_console import cout
14from apio.common.apio_styles import EMPH1
15from apio.managers.scons_manager import SConsManager
16from apio.commands import options
17from apio.apio_context import (
18 ApioContext,
19 PackagesPolicy,
20 ProjectPolicy,
21 RemoteConfigPolicy,
22)
23from apio.common.proto.apio_scons_pb2 import SimParams
24from apio.utils import cmd_util
27# --------- apio sim
30# -- Text in the rich-text format of the python rich library.
31APIO_SIM_HELP = """
32The command 'apio sim' simulates the default or the specified testbench file \
33and displays its simulation results in a graphical GTKWave window. \
34The testbench is expected to have a name ending with _tb, such as \
35'main_tb.v' or 'main_tb.sv'. The default testbench file can be specified \
36using the apio.ini option 'default-testbench'. If 'default-testbench' is not \
37specified and the project has exactly one testbench file, that file will be \
38used as the default testbench.
40Example:[code]
41 apio sim # Simulate the default testbench.
42 apio sim my_module_tb.v # Simulate the specified testbench.
43 apio sim my_module_tb.sv # Simulate the specified testbench.
44 apio sim util/led_tb.v # Simulate a testbench in a sub-folder.
45 apio sim --no-gtkwave # Simulate but skip GTKWave.
46 apio sim --detach # Launch and forget gtkwave.[/code]
48[IMPORTANT] Do not call the Verilog '$dumpfile()' function in your \
49testbenches: Apio treats it as a fatal error because it would override \
50the default name and location Apio sets for the generated .vcd file.
52[NOTE] Testbench specification is always the testbench file path relative to \
53the project directory, even if using the '--project-dir' option.
55[NOTE] If the testbench doesn't have a matching user-saved '.gtkw' file, \
56'apio sim' creates it automatically on each run to to have GTKWave displaying \
57the testbench signals. To customize the presentation of the signals, modify \
58them in GTKWave and save your configuration using the \
59'File > Write Save File' menu command. The 'apio sim' command will never \
60overwrite a '.gtkw' files that were saved in this way.
62The sim command defines the macro 'APIO_SIM=1' which can be used by \
63testbenches to skip `$fatal` statements to have the simulation continue and \
64generate signals for the GTKWave viewer.
66[code]# Instead of this
67$fatal;
69# Use this
70if (!`APIO_SIM) $fatal;[/code]
72[b][Hint][/b] When configuring the signals in GTKWave, save the \
73configuration so you don’t need to repeat it each time you run the \
74simulation.
75"""
77no_gtkw_wave_option = click.option(
78 "no_gtkwave", # Var name.
79 "-n",
80 "--no-gtkwave",
81 is_flag=True,
82 help="Skip GTKWave",
83 cls=cmd_util.ApioOption,
84)
86detach_option = click.option(
87 "detach", # Var name.
88 "-d",
89 "--detach",
90 is_flag=True,
91 help="Launch and forget GTKWave.",
92 cls=cmd_util.ApioOption,
93)
96@click.command(
97 name="sim",
98 cls=cmd_util.ApioCommand,
99 short_help="Simulate a testbench with graphic results.",
100 help=APIO_SIM_HELP,
101)
102@click.pass_context
103@click.argument(
104 "testbench_path",
105 metavar="[TESTBENCH-PATH]",
106 nargs=1,
107 required=False,
108)
109@options.force_option_gen(short_help="Force simulation.")
110@options.env_option_gen()
111@no_gtkw_wave_option
112@detach_option
113@options.project_dir_option
114def cli(
115 _: click.Context,
116 *,
117 # Arguments
118 testbench_path: str,
119 # Options
120 force: bool,
121 env: str | None,
122 no_gtkwave: bool,
123 detach: bool,
124 project_dir: Path | None,
125):
126 """Implements the apio sim command. It simulates a single testbench
127 file and shows graphically the signal graphs.
128 """
130 # pylint: disable=too-many-arguments
132 # -- Create the apio context.
133 apio_ctx = ApioContext(
134 project_policy=ProjectPolicy.PROJECT_REQUIRED,
135 remote_config_policy=RemoteConfigPolicy.CACHED_OK,
136 packages_policy=PackagesPolicy.ENSURE_PACKAGES,
137 project_dir_arg=project_dir,
138 env_arg=env,
139 )
141 # -- Create the scons manager.
142 scons = SConsManager(apio_ctx)
144 # -- If testbench not given, try to get a default from apio.ini.
145 if not testbench_path:
146 # -- If the option is not specified, testbench is set to None and
147 # -- we issue an error message in the scons process.
148 testbench_path = apio_ctx.project.get_str_option(
149 "default-testbench", None
150 )
151 if testbench_path:
152 cout(f"Using default testbench: {testbench_path}", style=EMPH1)
154 # -- Construct the scons sim params.
155 sim_params = SimParams(
156 testbench_path=testbench_path if testbench_path else None,
157 force_sim=force,
158 no_gtkwave=no_gtkwave,
159 detach_gtkwave=detach,
160 )
162 # -- Simulate the project with the given parameters
163 exit_code = scons.sim(sim_params)
165 # -- Done!
166 sys.exit(exit_code)