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

56 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-04 20:52 +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 

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 from collections.abc import Callable 

39 

40 from tsfpga.module_list import ModuleList 

41 from tsfpga.vivado.project import VivadoProject 

42 

43 

44def main() -> None: 

45 """ 

46 Main function for building single FPGA projects. 

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

48 """ 

49 args = arguments(default_temp_dir=TSFPGA_EXAMPLES_TEMP_DIR) 

50 modules = get_tsfpga_example_modules() 

51 projects = BuildProjectList( 

52 modules=modules, 

53 project_filters=args.project_filters, 

54 include_netlist_not_top_builds=args.netlist_builds, 

55 no_color=args.no_color, 

56 ) 

57 

58 sys.exit( 

59 setup_and_run( 

60 modules=modules, 

61 projects=projects, 

62 args=args, 

63 collect_artifacts_function=collect_artifacts, 

64 ) 

65 ) 

66 

67 

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

69 modules: ModuleList, 

70 projects: BuildProjectList, 

71 args: argparse.Namespace, 

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

73) -> int: 

74 """ 

75 Setup and execute build projects one by one. 

76 As instructed by the arguments. 

77 

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

79 

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

81 

82 Arguments: 

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

84 modules will be included. 

85 projects: These build projects will be built. 

86 args: Command line argument namespace. 

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

88 Will be run after a successful implementation build. 

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

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

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

92 

93 Return: 

94 0 if everything passed, otherwise non-zero. 

95 Can be used for system exit code. 

96 """ 

97 if args.list_only: 

98 print(projects) 

99 return 0 

100 

101 if args.generate_registers_only: 

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

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

104 generate_register_artifacts( 

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

106 ) 

107 return 0 

108 

109 if args.open: 

110 for project in projects.projects: 

111 project.open( 

112 project_path=projects.get_build_project_path( 

113 project=project, projects_path=args.projects_path 

114 ) 

115 ) 

116 

117 return 0 

118 

119 if args.collect_artifacts_only: 

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

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

122 create_ok = True 

123 

124 else: 

125 create_ok = True 

126 

127 for project in projects.projects: 

128 project_path = projects.get_build_project_path( 

129 project=project, projects_path=args.projects_path 

130 ) 

131 

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

133 create_ok &= project.create( 

134 project_path=project_path, ip_cache_path=args.ip_cache_path 

135 ) 

136 

137 if not create_ok: 

138 return 1 

139 

140 if args.create_only: 

141 return 0 

142 

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

144 collect_artifacts_function = ( 

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

146 ) 

147 

148 if args.collect_artifacts_only: 

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

150 

151 for project in projects.projects: 

152 assert collect_artifacts_function( 

153 project=project, 

154 output_path=projects.get_build_project_output_path( 

155 project=project, projects_path=args.projects_path, output_path=args.output_path 

156 ), 

157 ) 

158 

159 return 0 

160 

161 build_ok = True 

162 for project in projects.projects: 

163 project_output_path = projects.get_build_project_output_path( 

164 project=project, projects_path=args.projects_path, output_path=args.output_path 

165 ) 

166 

167 build_result = project.build( 

168 project_path=projects.get_build_project_path( 

169 project=project, projects_path=args.projects_path 

170 ), 

171 output_path=project_output_path, 

172 synth_only=args.synth_only, 

173 from_impl=args.from_impl, 

174 ) 

175 build_ok &= build_result.success 

176 

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

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

179 

180 if build_ok: 

181 return 0 

182 

183 return 1 

184 

185 

186if __name__ == "__main__": 

187 main()