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

38 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-21 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 __future__ import annotations 

10 

11 

12class StringGenericValue: 

13 """ 

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

15 """ 

16 

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

18 """ 

19 Arguments: 

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

21 """ 

22 if not isinstance(value, str): 

23 raise TypeError( 

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

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

26 ) 

27 

28 if " " in value: 

29 raise ValueError( 

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

31 ) 

32 

33 self.value = value 

34 

35 def __str__(self) -> str: 

36 return self.value 

37 

38 

39class BitVectorGenericValue: 

40 """ 

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

42 """ 

43 

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

45 """ 

46 Arguments: 

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

48 """ 

49 if not isinstance(value, str): 

50 raise TypeError( 

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

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

53 ) 

54 

55 for bit_value in value: 

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

57 raise ValueError( 

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

59 f' Got "{value}".' 

60 ) 

61 

62 self.value = value 

63 

64 @property 

65 def length(self) -> int: 

66 """ 

67 The number of bits in the vector. 

68 """ 

69 return len(self.value) 

70 

71 def __str__(self) -> str: 

72 return self.value 

73 

74 

75def get_vivado_tcl_generic_value( 

76 value: bool | float | StringGenericValue | BitVectorGenericValue, 

77) -> str: 

78 """ 

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

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

81 

82 Arguments: 

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

84 

85 Return: 

86 The ``value`` formatted as TCL. 

87 """ 

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

89 if isinstance(value, bool): 

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

91 

92 if isinstance(value, int): 

93 return str(value) 

94 

95 if isinstance(value, float): 

96 return str(value) 

97 

98 if isinstance(value, BitVectorGenericValue): 

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

100 

101 if isinstance(value, StringGenericValue): 

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

103 

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

105 

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

107 # be used instead. 

108 if isinstance(value, str): 

109 message += ( 

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

111 ) 

112 

113 raise TypeError(message)