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

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""" 

9 

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 

25 

26 

27# --------- apio sim 

28 

29 

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. 

39 

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] 

47 

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. 

51 

52[NOTE] Testbench specification is always the testbench file path relative to \ 

53the project directory, even if using the '--project-dir' option. 

54 

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. 

61 

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. 

65 

66[code]# Instead of this 

67$fatal; 

68 

69# Use this 

70if (!`APIO_SIM) $fatal;[/code] 

71 

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""" 

76 

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) 

85 

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) 

94 

95 

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 """ 

129 

130 # pylint: disable=too-many-arguments 

131 

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 ) 

140 

141 # -- Create the scons manager. 

142 scons = SConsManager(apio_ctx) 

143 

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) 

153 

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 ) 

161 

162 # -- Simulate the project with the given parameters 

163 exit_code = scons.sim(sim_params) 

164 

165 # -- Done! 

166 sys.exit(exit_code)