Coverage for tsfpga/vivado/generics.py: 97%

38 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-07 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 

10# Standard libraries 

11from typing import Union 

12 

13 

14class StringGenericValue: 

15 """ 

16 Use this type for generic values of type ``string``. 

17 """ 

18 

19 def __init__(self, value: str) -> None: 

20 """ 

21 Arguments: 

22 value: A string of variable length with any content. 

23 """ 

24 if not isinstance(value, str): 

25 raise ValueError( 

26 f"Expected {self.__class__.__name__} value to be of type str." 

27 f' Got type="{type(value)}", value="{value}".' 

28 ) 

29 

30 if " " in value: 

31 raise ValueError( 

32 f'Expected {self.__class__.__name__} value to not contain spaces. Got "{value}".' 

33 ) 

34 

35 self.value = value 

36 

37 def __str__(self) -> str: 

38 return self.value 

39 

40 

41class BitVectorGenericValue: 

42 """ 

43 Use this type for generic values of type ``std_logic_vector``. 

44 """ 

45 

46 def __init__(self, value: str) -> None: 

47 """ 

48 Arguments: 

49 value: A string of variable length containing only "1" or "0". 

50 """ 

51 if not isinstance(value, str): 

52 raise ValueError( 

53 f"Expected {self.__class__.__name__} value to be of type str." 

54 f' Got type="{type(value)}", value="{value}".' 

55 ) 

56 

57 for bit_value in value: 

58 if bit_value not in ["1", "0"]: 

59 raise ValueError( 

60 f'Expected {self.__class__.__name__} value to contain only "1" or "0".' 

61 f' Got "{value}".' 

62 ) 

63 

64 self.value = value 

65 

66 @property 

67 def length(self) -> int: 

68 """ 

69 The number of bits in the vector. 

70 """ 

71 return len(self.value) 

72 

73 def __str__(self) -> str: 

74 return self.value 

75 

76 

77def get_vivado_tcl_generic_value( 

78 value: Union[bool, int, float, StringGenericValue, BitVectorGenericValue] 

79) -> str: 

80 """ 

81 Convert generic values of different types to the format recognized by Vivado TCL: 

82 https://www.xilinx.com/support/answers/52217.html 

83 

84 Arguments: 

85 value: A generic value of native Python type.. 

86 

87 Return: 

88 The ``value`` formatted as TCL. 

89 """ 

90 # Note that bool is a sub-class of int in Python, so check for bool must be first 

91 if isinstance(value, bool): 

92 return f"1'b{int(value)}" 

93 

94 if isinstance(value, int): 

95 return str(value) 

96 

97 if isinstance(value, float): 

98 return str(value) 

99 

100 if isinstance(value, BitVectorGenericValue): 

101 return f"{value.length}'b{value.value}" 

102 

103 if isinstance(value, StringGenericValue): 

104 return f'"{value.value}"' 

105 

106 message = f'Unsupported type for generic. Got type="{type(value)}", value="{value}".' 

107 

108 # When the type is a string, we can be a little more helpful and indicate what types shall 

109 # be used instead. 

110 if isinstance(value, str): 

111 message += ( 

112 " Please use either of the explicit types StringGenericValue or BitVectorGenericValue." 

113 ) 

114 

115 raise ValueError(message)