pyadi-jif 0.1.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adijif/__init__.py +32 -0
- adijif/adijif.py +1 -0
- adijif/cli.py +21 -0
- adijif/clocks/__init__.py +10 -0
- adijif/clocks/ad9523.py +321 -0
- adijif/clocks/ad9523_1_bf.py +91 -0
- adijif/clocks/ad9528.py +444 -0
- adijif/clocks/ad9528_bf.py +70 -0
- adijif/clocks/ad9545.py +553 -0
- adijif/clocks/clock.py +153 -0
- adijif/clocks/hmc7044.py +558 -0
- adijif/clocks/hmc7044_bf.py +68 -0
- adijif/clocks/ltc6952.py +624 -0
- adijif/clocks/ltc6952_bf.py +67 -0
- adijif/clocks/ltc6953.py +509 -0
- adijif/common.py +70 -0
- adijif/converters/__init__.py +3 -0
- adijif/converters/ad9081.py +679 -0
- adijif/converters/ad9081_dp.py +206 -0
- adijif/converters/ad9081_util.py +124 -0
- adijif/converters/ad9084.py +588 -0
- adijif/converters/ad9084_dp.py +111 -0
- adijif/converters/ad9084_draw.py +203 -0
- adijif/converters/ad9084_util.py +365 -0
- adijif/converters/ad9144.py +316 -0
- adijif/converters/ad9144_bf.py +44 -0
- adijif/converters/ad9680.py +201 -0
- adijif/converters/ad9680_bf.py +43 -0
- adijif/converters/ad9680_draw.py +184 -0
- adijif/converters/adc.py +83 -0
- adijif/converters/adrv9009.py +426 -0
- adijif/converters/adrv9009_bf.py +43 -0
- adijif/converters/adrv9009_util.py +89 -0
- adijif/converters/converter.py +399 -0
- adijif/converters/dac.py +85 -0
- adijif/converters/resources/AD9084_JTX_JRX.xlsx +0 -0
- adijif/converters/resources/ad9081_JRx_204B.csv +180 -0
- adijif/converters/resources/ad9081_JRx_204C.csv +411 -0
- adijif/converters/resources/ad9081_JTx_204B.csv +1488 -0
- adijif/converters/resources/ad9081_JTx_204C.csv +1064 -0
- adijif/converters/resources/full_rx_mode_table_ad9081.csv +1904 -0
- adijif/converters/resources/full_tx_mode_table_ad9081.csv +994 -0
- adijif/d2/__init__.py +26 -0
- adijif/d2/d2lib.h +81 -0
- adijif/draw.py +498 -0
- adijif/fpgas/__init__.py +1 -0
- adijif/fpgas/fpga.py +64 -0
- adijif/fpgas/xilinx/__init__.py +1143 -0
- adijif/fpgas/xilinx/bf.py +101 -0
- adijif/fpgas/xilinx/pll.py +232 -0
- adijif/fpgas/xilinx/sevenseries.py +531 -0
- adijif/fpgas/xilinx/ultrascaleplus.py +485 -0
- adijif/fpgas/xilinx/xilinx_draw.py +516 -0
- adijif/gekko_trans.py +295 -0
- adijif/jesd.py +760 -0
- adijif/plls/__init__.py +3 -0
- adijif/plls/adf4030.py +259 -0
- adijif/plls/adf4371.py +419 -0
- adijif/plls/adf4382.py +581 -0
- adijif/plls/pll.py +103 -0
- adijif/solvers.py +54 -0
- adijif/sys/__init__.py +1 -0
- adijif/sys/s_plls.py +185 -0
- adijif/system.py +567 -0
- adijif/system_draw.py +65 -0
- adijif/types.py +151 -0
- adijif/utils.py +191 -0
- pyadi_jif-0.1.0.dist-info/METADATA +62 -0
- pyadi_jif-0.1.0.dist-info/RECORD +73 -0
- pyadi_jif-0.1.0.dist-info/WHEEL +6 -0
- pyadi_jif-0.1.0.dist-info/licenses/AUTHORS.rst +13 -0
- pyadi_jif-0.1.0.dist-info/licenses/LICENSE +277 -0
- pyadi_jif-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# flake8: noqa
|
|
2
|
+
from adijif.fpgas.fpga import fpga
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class xilinx_bf(fpga):
|
|
6
|
+
"""Brute force methods for calculating clocks
|
|
7
|
+
|
|
8
|
+
These are currently meant for debug to compare against
|
|
9
|
+
the solver solutions
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def determine_cpll(self, bit_clock, fpga_ref_clock):
|
|
13
|
+
"""
|
|
14
|
+
Parameters:
|
|
15
|
+
bit_clock:
|
|
16
|
+
Equivalent to lane rate in bits/second
|
|
17
|
+
fpga_ref_clock:
|
|
18
|
+
System reference clock
|
|
19
|
+
"""
|
|
20
|
+
assert isinstance(bit_clock, int), "bit_clock must be an int"
|
|
21
|
+
assert isinstance(fpga_ref_clock, int), "fpga_ref_clock must be an int"
|
|
22
|
+
|
|
23
|
+
# VCO = ( REF_CLK * N1 * N2 ) / M
|
|
24
|
+
# bit_clock = ( VCO * 2 ) / D
|
|
25
|
+
|
|
26
|
+
for m in [1, 2]:
|
|
27
|
+
for d in [1, 2, 4, 8]:
|
|
28
|
+
for n1 in [5, 4]:
|
|
29
|
+
for n2 in [5, 4, 3, 2, 1]:
|
|
30
|
+
vco = fpga_ref_clock * n1 * n2 / m
|
|
31
|
+
# print("VCO", self.vco_min/1e9, vco/1e9, self.vco_max/1e9)
|
|
32
|
+
if vco > self.vco_max or vco < self.vco_min:
|
|
33
|
+
continue
|
|
34
|
+
# print("VCO", vco)
|
|
35
|
+
# fpga_lane_rate = vco * 2 / d
|
|
36
|
+
# print("lane rate", fpga_lane_rate)
|
|
37
|
+
|
|
38
|
+
# VCO == 5,10,20,40 GHz
|
|
39
|
+
|
|
40
|
+
# print(fpga_ref_clock / m / d, bit_clock / (2 * n1 * n2))
|
|
41
|
+
if fpga_ref_clock / m / d == bit_clock / (2 * n1 * n2):
|
|
42
|
+
return {
|
|
43
|
+
"vco": vco,
|
|
44
|
+
"d": d,
|
|
45
|
+
"m": m,
|
|
46
|
+
"n1": n1,
|
|
47
|
+
"n2": n2,
|
|
48
|
+
"type": "CPLL",
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
raise Exception("No valid CPLL configuration found")
|
|
52
|
+
|
|
53
|
+
def determine_qpll(self, bit_clock, fpga_ref_clock):
|
|
54
|
+
"""
|
|
55
|
+
Parameters:
|
|
56
|
+
bit_clock:
|
|
57
|
+
Equivalent to lane rate in bits/second
|
|
58
|
+
fpga_ref_clock:
|
|
59
|
+
System reference clock
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
if self.ref_clock_max < fpga_ref_clock or fpga_ref_clock < self.ref_clock_min:
|
|
63
|
+
raise Exception("fpga_ref_clock not within range")
|
|
64
|
+
|
|
65
|
+
for m in [1, 2, 3, 4]:
|
|
66
|
+
for d in [1, 2, 4, 8, 16]:
|
|
67
|
+
for n in self.N:
|
|
68
|
+
vco = fpga_ref_clock * n / m
|
|
69
|
+
if self.vco1_min <= vco <= self.vco1_max:
|
|
70
|
+
band = 1
|
|
71
|
+
elif self.vco0_min <= vco <= self.vco0_max:
|
|
72
|
+
band = 0
|
|
73
|
+
else:
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
if fpga_ref_clock / m / d == bit_clock / n:
|
|
77
|
+
return {
|
|
78
|
+
"vco": vco,
|
|
79
|
+
"band": band,
|
|
80
|
+
"d": d,
|
|
81
|
+
"m": m,
|
|
82
|
+
"n": n,
|
|
83
|
+
"qty4_full_rate": 0,
|
|
84
|
+
"type": "QPLL",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if self.transciever_type != "GTY4":
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
if fpga_ref_clock / m / d == bit_clock / 2 / n:
|
|
91
|
+
return {
|
|
92
|
+
"vco": vco,
|
|
93
|
+
"band": band,
|
|
94
|
+
"d": d,
|
|
95
|
+
"m": m,
|
|
96
|
+
"n": n,
|
|
97
|
+
"qty4_full_rate": 1,
|
|
98
|
+
"type": "QPLL",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
raise Exception("No valid QPLL configuration found")
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""Xilinx Common PLL class."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional, Union
|
|
4
|
+
|
|
5
|
+
from docplex.cp.solution import CpoSolveResult # type: ignore
|
|
6
|
+
|
|
7
|
+
from ...common import core
|
|
8
|
+
from ...gekko_trans import gekko_translation
|
|
9
|
+
from ...solvers import CpoModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class XilinxPLL(core, gekko_translation):
|
|
13
|
+
"""Xilinx Common PLL class."""
|
|
14
|
+
|
|
15
|
+
plls = None
|
|
16
|
+
parent = None
|
|
17
|
+
_model = None # Hold internal model when used standalone
|
|
18
|
+
_solution = None # Hold internal solution when used standalone
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
parent=None, # noqa: ANN001
|
|
23
|
+
speed_grade: Optional[str] = "-2",
|
|
24
|
+
transceiver_type: Optional[str] = "GTXE2",
|
|
25
|
+
*args, # noqa: ANN002
|
|
26
|
+
**kwargs, # noqa: ANN003
|
|
27
|
+
) -> None:
|
|
28
|
+
"""Initalize 7 series transceiver PLLs.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
parent (system or converter, optional): Parent object. Defaults to None.
|
|
32
|
+
speed_grade (str, optional): Speed grade. Defaults to "-2".
|
|
33
|
+
transceiver_type (str, optional): Transceiver type. Defaults to "GTXE2".
|
|
34
|
+
*args: Variable length argument list.
|
|
35
|
+
**kwargs: Arbitrary keyword arguments.
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
Exception: If Gekko solver is used
|
|
39
|
+
"""
|
|
40
|
+
self.transceiver_type = transceiver_type
|
|
41
|
+
self.speed_grade = speed_grade
|
|
42
|
+
super().__init__(*args, **kwargs)
|
|
43
|
+
self.parent = parent
|
|
44
|
+
if parent:
|
|
45
|
+
self._model = parent.model
|
|
46
|
+
self._solution = parent.solution
|
|
47
|
+
self.solver = parent.solver
|
|
48
|
+
self.add_plls()
|
|
49
|
+
if self.solver == "gekko":
|
|
50
|
+
raise Exception("Gekko solver not supported for Xilinx PLLs")
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def model(self) -> CpoModel:
|
|
54
|
+
"""Internal system model for solver.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
CpoModel: Internal system model for solver
|
|
58
|
+
"""
|
|
59
|
+
if self.parent:
|
|
60
|
+
return self.parent.model
|
|
61
|
+
return self._model
|
|
62
|
+
|
|
63
|
+
@model.setter
|
|
64
|
+
def model(self, val: CpoModel) -> None:
|
|
65
|
+
"""Set internal system model for solver.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
val (CpoModel): Internal system model for solver
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
Exception: If parent model is used
|
|
72
|
+
"""
|
|
73
|
+
if self.parent:
|
|
74
|
+
raise Exception("Cannot set model when parent model is used")
|
|
75
|
+
self._model = val
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def solution(self) -> CpoSolveResult:
|
|
79
|
+
"""Solution object from solver."""
|
|
80
|
+
if self.parent:
|
|
81
|
+
return self.parent.solution
|
|
82
|
+
return self._solution
|
|
83
|
+
|
|
84
|
+
@solution.setter
|
|
85
|
+
def solution(self, val: CpoSolveResult) -> None:
|
|
86
|
+
"""Set solution object from solver.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
val (CpoSolveResult): Solution object from solver
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
Exception: If parent model is used
|
|
93
|
+
"""
|
|
94
|
+
if self.parent:
|
|
95
|
+
raise Exception("Cannot set solution when parent model is used")
|
|
96
|
+
self._solution = val
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def transceiver_type(self) -> str:
|
|
100
|
+
"""Transceiver type.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
str: Transceiver type
|
|
104
|
+
"""
|
|
105
|
+
return self._transceiver_type
|
|
106
|
+
|
|
107
|
+
@transceiver_type.setter
|
|
108
|
+
def transceiver_type(self, val: str) -> None:
|
|
109
|
+
"""Set transceiver type.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
val (str): Transceiver type
|
|
113
|
+
"""
|
|
114
|
+
self._check_in_range(val, self.transceiver_types_available, "transceiver_type")
|
|
115
|
+
self._transceiver_type = val
|
|
116
|
+
|
|
117
|
+
_speed_grade = -2
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def speed_grade(self) -> str:
|
|
121
|
+
"""speed_grade for transceiver.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
str: Speed grade
|
|
125
|
+
"""
|
|
126
|
+
if self.parent:
|
|
127
|
+
return self.parent.speed_grade
|
|
128
|
+
return self._speed_grade
|
|
129
|
+
|
|
130
|
+
@speed_grade.setter
|
|
131
|
+
def speed_grade(self, val: str) -> None:
|
|
132
|
+
"""Set speed grade for transceiver.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
val (str): Speed grade
|
|
136
|
+
|
|
137
|
+
Raises:
|
|
138
|
+
Exception: If parent model is used
|
|
139
|
+
"""
|
|
140
|
+
if self.parent:
|
|
141
|
+
raise Exception("Cannot set speed_grade when parent model is used")
|
|
142
|
+
self._speed_grade = val
|
|
143
|
+
|
|
144
|
+
def _solve_gekko(self) -> bool:
|
|
145
|
+
"""Local solve method for clock model.
|
|
146
|
+
|
|
147
|
+
Call model solver with correct arguments.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
bool: Always False
|
|
151
|
+
"""
|
|
152
|
+
self.model.options.SOLVER = 1 # APOPT solver
|
|
153
|
+
self.model.solver_options = [
|
|
154
|
+
"minlp_maximum_iterations 1000", # minlp iterations with integer solution
|
|
155
|
+
"minlp_max_iter_with_int_sol 100", # treat minlp as nlp
|
|
156
|
+
"minlp_as_nlp 0", # nlp sub-problem max iterations
|
|
157
|
+
"nlp_maximum_iterations 500", # 1 = depth first, 2 = breadth first
|
|
158
|
+
"minlp_branch_method 1", # maximum deviation from whole number
|
|
159
|
+
"minlp_integer_tol 0", # covergence tolerance (MUST BE 0 TFC)
|
|
160
|
+
"minlp_gap_tol 0.1",
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
self.model.solve(disp=False)
|
|
164
|
+
self.model.cleanup()
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
# def _add_objective(self, sysrefs: List) -> None:
|
|
168
|
+
# pass
|
|
169
|
+
|
|
170
|
+
def _solve_cplex(self) -> CpoSolveResult:
|
|
171
|
+
self.solution = self.model.solve(LogVerbosity="Normal")
|
|
172
|
+
if self.solution.solve_status not in ["Feasible", "Optimal"]:
|
|
173
|
+
raise Exception("Solution Not Found")
|
|
174
|
+
return self.solution
|
|
175
|
+
|
|
176
|
+
def solve(self) -> Union[None, CpoSolveResult]:
|
|
177
|
+
"""Local solve method for clock model.
|
|
178
|
+
|
|
179
|
+
Call model solver with correct arguments.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
[None,CpoSolveResult]: When cplex solver is used CpoSolveResult is returned
|
|
183
|
+
|
|
184
|
+
Raises:
|
|
185
|
+
Exception: If solver is not valid
|
|
186
|
+
|
|
187
|
+
"""
|
|
188
|
+
if self.solver == "gekko":
|
|
189
|
+
return self._solve_gekko()
|
|
190
|
+
elif self.solver == "CPLEX":
|
|
191
|
+
return self._solve_cplex()
|
|
192
|
+
else:
|
|
193
|
+
raise Exception(f"Unknown solver {self.solver}")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class PLLCommon(gekko_translation):
|
|
197
|
+
"""Common PLL class for Xilinx and Intel PLLs."""
|
|
198
|
+
|
|
199
|
+
def __init__(self, parent_transceiver: CpoModel) -> None:
|
|
200
|
+
"""Initialize PLL common class.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
parent_transceiver (CpoModel): Parent transceiver object
|
|
204
|
+
"""
|
|
205
|
+
self.parent = parent_transceiver
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def model(self) -> CpoModel:
|
|
209
|
+
"""Internal system model for solver.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
CpoModel: Internal system model for solver
|
|
213
|
+
"""
|
|
214
|
+
return self.parent.model
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def solver(self) -> str:
|
|
218
|
+
"""Solver type.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
str: Solver type
|
|
222
|
+
"""
|
|
223
|
+
return self.parent.solver
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def solution(self) -> CpoSolveResult:
|
|
227
|
+
"""Solution object from solver.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
CpoSolveResult: Solution object from solver
|
|
231
|
+
"""
|
|
232
|
+
return self.parent.solution
|