Coverage for tsfpga/examples/build_fpga_single_project.py: 0%

56 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-08-29 20:51 +0000

1# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the tsfpga project, a project platform for modern FPGA development. 

5# https://tsfpga.com 

6# https://github.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9""" 

10Build FPGA projects from the command line. 

11Note that this is an example script that illustrates how FPGA build projects can be built one 

12by one. 

13This is not the recommended standard build flow, see 'build_fpga.py' instead. 

14 

15The benefit of building one by one is that build status is written directly to STDOUT. 

16""" 

17 

18from __future__ import annotations 

19 

20import sys 

21from pathlib import Path 

22from typing import TYPE_CHECKING, Callable 

23 

24# Do PYTHONPATH insert() instead of append() to prefer any local repo checkout over any pip install. 

25REPO_ROOT = Path(__file__).parent.parent.parent.resolve() 

26sys.path.insert(0, str(REPO_ROOT)) 

27 

28# Import before others since it modifies PYTHONPATH. 

29import tsfpga.examples.example_pythonpath # noqa: F401 

30 

31from tsfpga.build_project_list import BuildProjectList 

32from tsfpga.examples.build_fpga import collect_artifacts 

33from tsfpga.examples.build_fpga_utils import arguments, generate_register_artifacts 

34from tsfpga.examples.example_env import TSFPGA_EXAMPLES_TEMP_DIR, get_tsfpga_example_modules 

35 

36if TYPE_CHECKING: 

37 import argparse 

38 

39 from tsfpga.module_list import ModuleList 

40 from tsfpga.vivado.project import VivadoProject 

41 

42 

43def main() -> None: 

44 """ 

45 Main function for building single FPGA projects. 

46 Note that this is not the recommended standard build flow, see 'build_fpga.py' instead. 

47 """ 

48 args = arguments(default_temp_dir=TSFPGA_EXAMPLES_TEMP_DIR) 

49 modules = get_tsfpga_example_modules() 

50 projects = BuildProjectList( 

51 modules=modules, 

52 project_filters=args.project_filters, 

53 include_netlist_not_top_builds=args.netlist_builds, 

54 no_color=args.no_color, 

55 ) 

56 

57 sys.exit( 

58 setup_and_run( 

59 modules=modules, 

60 projects=projects, 

61 args=args, 

62 collect_artifacts_function=collect_artifacts, 

63 ) 

64 ) 

65 

66 

67def setup_and_run( # noqa: C901, PLR0911, PLR0912 

68 modules: ModuleList, 

69 projects: BuildProjectList, 

70 args: argparse.Namespace, 

71 collect_artifacts_function: Callable[[VivadoProject, Path], bool] | None, 

72) -> int: 

73 """ 

74 Setup and execute build projects one by one. 

75 As instructed by the arguments. 

76 

77 Note that this is not the recommended standard build flow, see 'build_fpga.py' instead. 

78 

79 Note that this functions is a modified clone of the one in 'build_fpga_utils.py'. 

80 

81 Arguments: 

82 modules: When running a register generation, registers from these 

83 modules will be included. 

84 projects: These build projects will be built. 

85 args: Command line argument namespace. 

86 collect_artifacts_function: Function pointer to a function that collects build artifacts. 

87 Will be run after a successful implementation build. 

88 The function must return ``True`` if successful and ``False`` otherwise. 

89 It will receive the ``project`` and ``output_path`` as arguments. 

90 Can be ``None`` if no special artifact collection operation shall be run. 

91 

92 Return: 

93 0 if everything passed, otherwise non-zero. 

94 Can be used for system exit code. 

95 """ 

96 if args.list_only: 

97 print(projects) 

98 return 0 

99 

100 if args.generate_registers_only: 

101 # Generate register output from all modules. Note that this is not used by the 

102 # build flow or simulation flow, it is only for the user to inspect the artifacts. 

103 generate_register_artifacts( 

104 modules=modules, output_path=args.projects_path.parent / "registers" 

105 ) 

106 return 0 

107 

108 if args.open: 

109 for project in projects.projects: 

110 project.open( 

111 project_path=projects.get_build_project_path( 

112 project=project, projects_path=args.projects_path 

113 ) 

114 ) 

115 

116 return 0 

117 

118 if args.collect_artifacts_only: 

119 # We have to assume that the projects exist if the user sent this argument. 

120 # The 'collect_artifacts_function' call below will probably fail if it does not. 

121 create_ok = True 

122 

123 else: 

124 create_ok = True 

125 

126 for project in projects.projects: 

127 project_path = projects.get_build_project_path( 

128 project=project, projects_path=args.projects_path 

129 ) 

130 

131 if (not args.use_existing_project) or (not project_path.exists()): 

132 create_ok &= project.create( 

133 project_path=project_path, ip_cache_path=args.ip_cache_path 

134 ) 

135 

136 if not create_ok: 

137 return 1 

138 

139 if args.create_only: 

140 return 0 

141 

142 # If doing only synthesis, there are no artifacts to collect. 

143 collect_artifacts_function = ( 

144 None if (args.synth_only or args.netlist_builds) else collect_artifacts_function 

145 ) 

146 

147 if args.collect_artifacts_only: 

148 assert collect_artifacts_function is not None, "No artifact collection available" 

149 

150 for project in projects.projects: 

151 assert collect_artifacts_function( 

152 project=project, 

153 output_path=projects.get_build_project_output_path( 

154 project=project, projects_path=args.projects_path, output_path=args.output_path 

155 ), 

156 ) 

157 

158 return 0 

159 

160 build_ok = True 

161 for project in projects.projects: 

162 project_output_path = projects.get_build_project_output_path( 

163 project=project, projects_path=args.projects_path, output_path=args.output_path 

164 ) 

165 

166 build_result = project.build( 

167 project_path=projects.get_build_project_path( 

168 project=project, projects_path=args.projects_path 

169 ), 

170 output_path=project_output_path, 

171 synth_only=args.synth_only, 

172 from_impl=args.from_impl, 

173 ) 

174 build_ok &= build_result.success 

175 

176 if build_result.success and (collect_artifacts_function is not None): 

177 build_ok &= collect_artifacts_function(project=project, output_path=project_output_path) 

178 

179 if build_ok: 

180 return 0 

181 

182 return 1 

183 

184 

185if __name__ == "__main__": 

186 main()