Coverage for tsfpga/vivado/test/test_ip_cores.py: 100%

93 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-01 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 

9from unittest.mock import MagicMock, patch 

10 

11import pytest 

12 

13from tsfpga.ip_core_file import IpCoreFile 

14from tsfpga.module import BaseModule, get_modules 

15from tsfpga.system_utils import create_file, delete 

16from tsfpga.vivado.ip_cores import VivadoIpCores 

17 

18 

19def test_get_ip_core_files_is_called_with_the_correct_arguments(tmp_path): 

20 modules = [MagicMock(spec=BaseModule)] 

21 

22 with patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True): 

23 VivadoIpCores(modules, tmp_path, part_name="test_part") 

24 

25 modules[0].get_ip_core_files.assert_called_once_with(generics={}, part="test_part") 

26 

27 

28def test_system_call_to_vivado_failing_should_raise_exception(tmp_path): 

29 project = VivadoIpCores(modules=[], output_path=tmp_path, part_name="test_part") 

30 

31 with patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) as create: 

32 create.return_value = False 

33 

34 with pytest.raises(RuntimeError) as exception_info: 

35 project.create_vivado_project_if_needed() 

36 

37 assert str(exception_info.value) == "Failed to create Vivado IP core project" 

38 

39 

40@pytest.fixture 

41def ip_cores_test(tmp_path): 

42 class IpCoresTest: 

43 def __init__(self): 

44 self.project_folder = tmp_path / "ip_project" 

45 self.modules_folder = tmp_path / "modules" 

46 

47 self.apa_tcl = create_file(self.modules_folder / "apa" / "ip_cores" / "apa.tcl", "apa") 

48 self.hest_tcl = create_file( 

49 self.modules_folder / "hest" / "ip_cores" / "hest.tcl", "hest" 

50 ) 

51 

52 modules = get_modules(self.modules_folder) 

53 self.vivado_ip_cores = VivadoIpCores(modules, self.project_folder, part_name="-") 

54 

55 # Create initial hash and (empty) compile order file 

56 self.vivado_ip_cores._save_hash() # noqa: SLF001 

57 self.create_compile_order_file() 

58 

59 def create_compile_order_file(self): 

60 create_file(self.vivado_ip_cores.compile_order_file) 

61 

62 return IpCoresTest() 

63 

64 

65@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

66def test_should_not_recreate(create, ip_cores_test): 

67 assert not ip_cores_test.vivado_ip_cores.create_vivado_project_if_needed() 

68 create.assert_not_called() 

69 

70 

71@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

72def test_should_recreate_if_compile_order_file_is_missing(create, ip_cores_test): 

73 delete(ip_cores_test.vivado_ip_cores.compile_order_file) 

74 assert ip_cores_test.vivado_ip_cores.create_vivado_project_if_needed() 

75 create.assert_called_once() 

76 

77 

78@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

79def test_should_recreate_if_hash_file_is_missing(create, ip_cores_test): 

80 delete(ip_cores_test.vivado_ip_cores._hash_file) # noqa: SLF001 

81 assert ip_cores_test.vivado_ip_cores.create_vivado_project_if_needed() 

82 create.assert_called_once() 

83 

84 

85@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

86def test_should_not_recreate_if_nothing_is_changed(create, ip_cores_test): 

87 # This test shows that the pattern used in the upcoming tests: 

88 # change something -> get modules -> create new VivadoIpCores object 

89 # should not result in a recreate unless we actually change something. 

90 modules = get_modules(ip_cores_test.modules_folder) 

91 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

92 

93 assert not vivado_ip_cores.create_vivado_project_if_needed() 

94 create.assert_not_called() 

95 

96 

97@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

98def test_should_recreate_if_ip_core_file_is_added(create, ip_cores_test): 

99 create_file(ip_cores_test.modules_folder / "zebra" / "ip_cores" / "zebra.tcl", "zebra") 

100 modules = get_modules(ip_cores_test.modules_folder) 

101 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

102 

103 assert vivado_ip_cores.create_vivado_project_if_needed() 

104 create.assert_called_once() 

105 

106 

107@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

108def test_should_recreate_if_ip_core_file_is_removed(create, ip_cores_test): 

109 delete(ip_cores_test.hest_tcl) 

110 modules = get_modules(ip_cores_test.modules_folder) 

111 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

112 

113 assert vivado_ip_cores.create_vivado_project_if_needed() 

114 create.assert_called_once() 

115 

116 

117@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

118def test_should_recreate_if_ip_core_file_is_changed(create, ip_cores_test): 

119 create_file(ip_cores_test.apa_tcl, "blaha blaha") 

120 modules = get_modules(ip_cores_test.modules_folder) 

121 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

122 

123 assert vivado_ip_cores.create_vivado_project_if_needed() 

124 create.assert_called_once() 

125 

126 

127@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

128def test_ip_core_variables(create, ip_cores_test): 

129 modules = [MagicMock(spec=BaseModule)] 

130 

131 modules[0].get_ip_core_files.return_value = [IpCoreFile(path=ip_cores_test.apa_tcl)] 

132 

133 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

134 

135 assert vivado_ip_cores.create_vivado_project_if_needed() 

136 assert create.call_count == 1 

137 ip_cores_test.create_compile_order_file() 

138 

139 # Should not recreate until we change something 

140 assert not vivado_ip_cores.create_vivado_project_if_needed() 

141 assert create.call_count == 1 

142 

143 # Adding variables should recreate 

144 modules[0].get_ip_core_files.return_value = [ 

145 IpCoreFile(path=ip_cores_test.apa_tcl, zz="123", aa="456") 

146 ] 

147 

148 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

149 

150 assert vivado_ip_cores.create_vivado_project_if_needed() 

151 assert create.call_count == 2 

152 ip_cores_test.create_compile_order_file() 

153 

154 # Changing order of variables should not recreate 

155 modules[0].get_ip_core_files.return_value = [ 

156 IpCoreFile(path=ip_cores_test.apa_tcl, aa="456", zz="123") 

157 ] 

158 

159 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

160 

161 assert not vivado_ip_cores.create_vivado_project_if_needed() 

162 assert create.call_count == 2