Coverage for tsfpga/vivado/build_result_checker.py: 98%

58 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-29 20:01 +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://gitlab.com/tsfpga/tsfpga 

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

8 

9 

10class LessThan: 

11 

12 """ 

13 Limit to be used with a checker to see that a figure is less than the specified value. 

14 """ 

15 

16 def __init__(self, value): 

17 """ 

18 Arguments: 

19 value (int): The result value shall be less than this. 

20 """ 

21 self.value = value 

22 

23 def check(self, result_value): 

24 return result_value < self.value 

25 

26 def __str__(self): 

27 return f"< {self.value}" 

28 

29 

30class EqualTo: 

31 

32 """ 

33 Limit to be used with a checker to see that a figure is equal to the specified value. 

34 """ 

35 

36 def __init__(self, value): 

37 """ 

38 Arguments: 

39 value (int): The result value shall be equal to this. 

40 """ 

41 self.value = value 

42 

43 def check(self, result_value): 

44 return result_value == self.value 

45 

46 def __str__(self): 

47 return str(self.value) 

48 

49 

50class BuildResultChecker: 

51 

52 """ 

53 Check a build result value against a limit. 

54 

55 Overload and implement the ``check`` method according to the resource you want to check. 

56 """ 

57 

58 def __init__(self, limit): 

59 """ 

60 Arguments: 

61 limit: The limit that the specified resource shall be checked against. Should 

62 be e.g. a :class:`LessThan` object. 

63 """ 

64 self.limit = limit 

65 

66 def check(self, build_result): 

67 """ 

68 Arguments: 

69 build_result (tsfpga.vivado.build_result.BuildResult): Build result that shall 

70 be checked. 

71 

72 Returns: 

73 bool: True if check passed, false otherwise. 

74 """ 

75 raise NotImplementedError("Implement in child class") 

76 

77 def _check_value(self, name, value): 

78 if self.limit.check(value): 

79 message = f"Result check passed for {name}: {value} ({self.limit})" 

80 print(message) 

81 return True 

82 

83 message = f"Result check failed for {name}. " f"Got {value}, expected {self.limit}." 

84 print(message) 

85 return False 

86 

87 

88class MaximumLogicLevel(BuildResultChecker): 

89 

90 """ 

91 Check the maximum logic level of a build result against a limit. 

92 """ 

93 

94 name = "Maximum logic level" 

95 

96 def check(self, build_result): 

97 return self._check_value("maximum logic level", build_result.maximum_logic_level) 

98 

99 

100class SizeChecker(BuildResultChecker): 

101 

102 """ 

103 Check a build result size value against a limit. 

104 

105 Overload and set the correct ``name``, according to the names 

106 in the vendor utilization report. 

107 

108 Note that since this is to be used by netlist builds it checks the synthesized size, not 

109 the implemented one, even if available. 

110 """ 

111 

112 name = "" 

113 

114 def check(self, build_result): 

115 return self._check_value(self.name, build_result.synthesis_size[self.name]) 

116 

117 

118class TotalLuts(SizeChecker): 

119 

120 name = "Total LUTs" 

121 

122 

123class LogicLuts(SizeChecker): 

124 

125 name = "Logic LUTs" 

126 

127 

128class LutRams(SizeChecker): 

129 

130 name = "LUTRAMs" 

131 

132 

133class Srls(SizeChecker): 

134 

135 name = "SRLs" 

136 

137 

138class Ffs(SizeChecker): 

139 

140 name = "FFs" 

141 

142 

143class Ramb36(SizeChecker): 

144 

145 name = "RAMB36" 

146 

147 

148class Ramb18(SizeChecker): 

149 

150 name = "RAMB18" 

151 

152 

153class Uram(SizeChecker): 

154 

155 name = "URAM" 

156 

157 

158class DspBlocks(SizeChecker): 

159 

160 """ 

161 In Vivado pre-2020.1 the resource was called "DSP48 Blocks" in the utilization report. 

162 After that it is called "DSP Blocks". This class checks for both. 

163 """ 

164 

165 name = "DSP Blocks" 

166 

167 def check(self, build_result): 

168 """ 

169 Same as parent class, but checks for the legacy name as well as the current name. 

170 """ 

171 legacy_name = "DSP48 Blocks" 

172 if legacy_name in build_result.synthesis_size: 

173 return self._check_value(legacy_name, build_result.synthesis_size[legacy_name]) 

174 

175 return self._check_value(self.name, build_result.synthesis_size[self.name])