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.
Files changed (73) hide show
  1. adijif/__init__.py +32 -0
  2. adijif/adijif.py +1 -0
  3. adijif/cli.py +21 -0
  4. adijif/clocks/__init__.py +10 -0
  5. adijif/clocks/ad9523.py +321 -0
  6. adijif/clocks/ad9523_1_bf.py +91 -0
  7. adijif/clocks/ad9528.py +444 -0
  8. adijif/clocks/ad9528_bf.py +70 -0
  9. adijif/clocks/ad9545.py +553 -0
  10. adijif/clocks/clock.py +153 -0
  11. adijif/clocks/hmc7044.py +558 -0
  12. adijif/clocks/hmc7044_bf.py +68 -0
  13. adijif/clocks/ltc6952.py +624 -0
  14. adijif/clocks/ltc6952_bf.py +67 -0
  15. adijif/clocks/ltc6953.py +509 -0
  16. adijif/common.py +70 -0
  17. adijif/converters/__init__.py +3 -0
  18. adijif/converters/ad9081.py +679 -0
  19. adijif/converters/ad9081_dp.py +206 -0
  20. adijif/converters/ad9081_util.py +124 -0
  21. adijif/converters/ad9084.py +588 -0
  22. adijif/converters/ad9084_dp.py +111 -0
  23. adijif/converters/ad9084_draw.py +203 -0
  24. adijif/converters/ad9084_util.py +365 -0
  25. adijif/converters/ad9144.py +316 -0
  26. adijif/converters/ad9144_bf.py +44 -0
  27. adijif/converters/ad9680.py +201 -0
  28. adijif/converters/ad9680_bf.py +43 -0
  29. adijif/converters/ad9680_draw.py +184 -0
  30. adijif/converters/adc.py +83 -0
  31. adijif/converters/adrv9009.py +426 -0
  32. adijif/converters/adrv9009_bf.py +43 -0
  33. adijif/converters/adrv9009_util.py +89 -0
  34. adijif/converters/converter.py +399 -0
  35. adijif/converters/dac.py +85 -0
  36. adijif/converters/resources/AD9084_JTX_JRX.xlsx +0 -0
  37. adijif/converters/resources/ad9081_JRx_204B.csv +180 -0
  38. adijif/converters/resources/ad9081_JRx_204C.csv +411 -0
  39. adijif/converters/resources/ad9081_JTx_204B.csv +1488 -0
  40. adijif/converters/resources/ad9081_JTx_204C.csv +1064 -0
  41. adijif/converters/resources/full_rx_mode_table_ad9081.csv +1904 -0
  42. adijif/converters/resources/full_tx_mode_table_ad9081.csv +994 -0
  43. adijif/d2/__init__.py +26 -0
  44. adijif/d2/d2lib.h +81 -0
  45. adijif/draw.py +498 -0
  46. adijif/fpgas/__init__.py +1 -0
  47. adijif/fpgas/fpga.py +64 -0
  48. adijif/fpgas/xilinx/__init__.py +1143 -0
  49. adijif/fpgas/xilinx/bf.py +101 -0
  50. adijif/fpgas/xilinx/pll.py +232 -0
  51. adijif/fpgas/xilinx/sevenseries.py +531 -0
  52. adijif/fpgas/xilinx/ultrascaleplus.py +485 -0
  53. adijif/fpgas/xilinx/xilinx_draw.py +516 -0
  54. adijif/gekko_trans.py +295 -0
  55. adijif/jesd.py +760 -0
  56. adijif/plls/__init__.py +3 -0
  57. adijif/plls/adf4030.py +259 -0
  58. adijif/plls/adf4371.py +419 -0
  59. adijif/plls/adf4382.py +581 -0
  60. adijif/plls/pll.py +103 -0
  61. adijif/solvers.py +54 -0
  62. adijif/sys/__init__.py +1 -0
  63. adijif/sys/s_plls.py +185 -0
  64. adijif/system.py +567 -0
  65. adijif/system_draw.py +65 -0
  66. adijif/types.py +151 -0
  67. adijif/utils.py +191 -0
  68. pyadi_jif-0.1.0.dist-info/METADATA +62 -0
  69. pyadi_jif-0.1.0.dist-info/RECORD +73 -0
  70. pyadi_jif-0.1.0.dist-info/WHEEL +6 -0
  71. pyadi_jif-0.1.0.dist-info/licenses/AUTHORS.rst +13 -0
  72. pyadi_jif-0.1.0.dist-info/licenses/LICENSE +277 -0
  73. pyadi_jif-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,68 @@
1
+ # flake8: noqa
2
+ import numpy as np
3
+
4
+ from adijif.clocks.clock import clock
5
+
6
+
7
+ class hmc7044_bf(clock):
8
+ """Brute force methods for calculating clocks
9
+
10
+ These are currently meant for debug to compare against
11
+ the solver solutions
12
+ """
13
+
14
+ def list_available_references(self, divider_set):
15
+ """list_available_references: Based on config list possible
16
+ references that can be generated based on VCO and output
17
+ dividers
18
+ """
19
+ # Check input
20
+ ref = {
21
+ "n2": 2,
22
+ "vco": 3000000000,
23
+ "r2": 24,
24
+ "required_output_divs": np.array([1.0]),
25
+ }
26
+ for key in ref:
27
+ if key not in divider_set:
28
+ raise Exception(
29
+ "Input must be of type dict with fields: " + str(ref.keys())
30
+ )
31
+ return [divider_set["vco"] / div for div in self.d_available]
32
+
33
+ def find_dividers(self, vcxo, rates, find=3):
34
+ if self.use_vcxo_double:
35
+ vcxo *= 2
36
+
37
+ even = np.arange(2, 4096, 2, dtype=int)
38
+ odivs = np.append([1, 3, 5], even)
39
+
40
+ rates = np.array(rates)
41
+ mod = np.gcd.reduce(np.array(rates, dtype=int))
42
+ vcos = []
43
+ configs = []
44
+
45
+ # for n in range(self.n2_divider_min, self.n2_divider_max):
46
+ for n in self.n2:
47
+ # for r in range(self.r2_divider_min, self.r2_divider_max):
48
+ for r in self.r2:
49
+ # Check VCO in range and output clock a multiple of required reference
50
+ f = vcxo * n / r
51
+ if f >= self.vco_min and f <= self.vco_max:
52
+ # Check if required dividers for output clocks are in set
53
+ if f % mod == 0:
54
+ d = f / rates
55
+ if np.all(np.in1d(d, odivs)) and f not in vcos:
56
+ if f not in vcos:
57
+ vcos.append(f)
58
+ config = {
59
+ "n2": n,
60
+ "r2": r,
61
+ "vco": f,
62
+ "required_output_divs": d,
63
+ }
64
+ configs.append(config)
65
+ if len(configs) >= find:
66
+ return configs
67
+
68
+ return configs
@@ -0,0 +1,624 @@
1
+ """LTC6952 clock chip model."""
2
+
3
+ from typing import Dict, List, Union
4
+
5
+ from docplex.cp.solution import CpoSolveResult # type: ignore
6
+
7
+ from adijif.clocks.ltc6952_bf import ltc6952_bf
8
+ from adijif.solvers import CpoExpr, GK_Intermediate
9
+
10
+
11
+ class ltc6952(ltc6952_bf):
12
+ """LTC6952 clock chip model.
13
+
14
+ This model currently supports VCXO+PLL2 configurations
15
+ """
16
+
17
+ name = "LTC6952"
18
+
19
+ vcxo = 125000000
20
+
21
+ # Ranges
22
+ r2_divider_min = 1
23
+ r2_divider_max = 1023
24
+ r2_available = [*range(1, 1023 + 1)]
25
+ n2_divider_min = 1
26
+ n2_divider_max = 65535
27
+ n2_available = [*range(1, 65535 + 1)]
28
+
29
+ """ Output dividers """
30
+ d_available = [
31
+ 1,
32
+ 2,
33
+ 3,
34
+ 4,
35
+ 5,
36
+ 6,
37
+ 7,
38
+ 8,
39
+ 9,
40
+ 10,
41
+ 11,
42
+ 12,
43
+ 13,
44
+ 14,
45
+ 15,
46
+ 16,
47
+ 17,
48
+ 18,
49
+ 19,
50
+ 20,
51
+ 21,
52
+ 22,
53
+ 23,
54
+ 24,
55
+ 25,
56
+ 26,
57
+ 27,
58
+ 28,
59
+ 29,
60
+ 30,
61
+ 31,
62
+ 32,
63
+ 34,
64
+ 36,
65
+ 38,
66
+ 40,
67
+ 42,
68
+ 44,
69
+ 46,
70
+ 48,
71
+ 50,
72
+ 52,
73
+ 54,
74
+ 56,
75
+ 58,
76
+ 60,
77
+ 62,
78
+ 64,
79
+ 68,
80
+ 72,
81
+ 76,
82
+ 80,
83
+ 84,
84
+ 88,
85
+ 92,
86
+ 96,
87
+ 100,
88
+ 104,
89
+ 108,
90
+ 112,
91
+ 116,
92
+ 120,
93
+ 124,
94
+ 128,
95
+ 136,
96
+ 144,
97
+ 152,
98
+ 160,
99
+ 168,
100
+ 176,
101
+ 184,
102
+ 192,
103
+ 200,
104
+ 208,
105
+ 216,
106
+ 224,
107
+ 232,
108
+ 240,
109
+ 248,
110
+ 256,
111
+ 272,
112
+ 288,
113
+ 304,
114
+ 320,
115
+ 336,
116
+ 352,
117
+ 368,
118
+ 384,
119
+ 400,
120
+ 416,
121
+ 432,
122
+ 448,
123
+ 464,
124
+ 480,
125
+ 496,
126
+ 512,
127
+ 544,
128
+ 576,
129
+ 608,
130
+ 640,
131
+ 672,
132
+ 704,
133
+ 736,
134
+ 768,
135
+ 800,
136
+ 832,
137
+ 864,
138
+ 896,
139
+ 928,
140
+ 960,
141
+ 992,
142
+ 1024,
143
+ 1088,
144
+ 1152,
145
+ 1216,
146
+ 1280,
147
+ 1344,
148
+ 1408,
149
+ 1472,
150
+ 1536,
151
+ 1600,
152
+ 1664,
153
+ 1728,
154
+ 1792,
155
+ 1856,
156
+ 1920,
157
+ 1984,
158
+ 2048,
159
+ 2176,
160
+ 2304,
161
+ 2432,
162
+ 2560,
163
+ 2688,
164
+ 2816,
165
+ 2944,
166
+ 3072,
167
+ 3200,
168
+ 3328,
169
+ 3456,
170
+ 3584,
171
+ 3712,
172
+ 3840,
173
+ 3968,
174
+ 4096,
175
+ ]
176
+
177
+ # Defaults
178
+ _d: Union[int, List[int]] = [
179
+ 1,
180
+ 2,
181
+ 3,
182
+ 4,
183
+ 5,
184
+ 6,
185
+ 7,
186
+ 8,
187
+ 9,
188
+ 10,
189
+ 11,
190
+ 12,
191
+ 13,
192
+ 14,
193
+ 15,
194
+ 16,
195
+ 17,
196
+ 18,
197
+ 19,
198
+ 20,
199
+ 21,
200
+ 22,
201
+ 23,
202
+ 24,
203
+ 25,
204
+ 26,
205
+ 27,
206
+ 28,
207
+ 29,
208
+ 30,
209
+ 31,
210
+ 32,
211
+ 34,
212
+ 36,
213
+ 38,
214
+ 40,
215
+ 42,
216
+ 44,
217
+ 46,
218
+ 48,
219
+ 50,
220
+ 52,
221
+ 54,
222
+ 56,
223
+ 58,
224
+ 60,
225
+ 62,
226
+ 64,
227
+ 68,
228
+ 72,
229
+ 76,
230
+ 80,
231
+ 84,
232
+ 88,
233
+ 92,
234
+ 96,
235
+ 100,
236
+ 104,
237
+ 108,
238
+ 112,
239
+ 116,
240
+ 120,
241
+ 124,
242
+ 128,
243
+ 136,
244
+ 144,
245
+ 152,
246
+ 160,
247
+ 168,
248
+ 176,
249
+ 184,
250
+ 192,
251
+ 200,
252
+ 208,
253
+ 216,
254
+ 224,
255
+ 232,
256
+ 240,
257
+ 248,
258
+ 256,
259
+ 272,
260
+ 288,
261
+ 304,
262
+ 320,
263
+ 336,
264
+ 352,
265
+ 368,
266
+ 384,
267
+ 400,
268
+ 416,
269
+ 432,
270
+ 448,
271
+ 464,
272
+ 480,
273
+ 496,
274
+ 512,
275
+ 544,
276
+ 576,
277
+ 608,
278
+ 640,
279
+ 672,
280
+ 704,
281
+ 736,
282
+ 768,
283
+ 800,
284
+ 832,
285
+ 864,
286
+ 896,
287
+ 928,
288
+ 960,
289
+ 992,
290
+ 1024,
291
+ 1088,
292
+ 1152,
293
+ 1216,
294
+ 1280,
295
+ 1344,
296
+ 1408,
297
+ 1472,
298
+ 1536,
299
+ 1600,
300
+ 1664,
301
+ 1728,
302
+ 1792,
303
+ 1856,
304
+ 1920,
305
+ 1984,
306
+ 2048,
307
+ 2176,
308
+ 2304,
309
+ 2432,
310
+ 2560,
311
+ 2688,
312
+ 2816,
313
+ 2944,
314
+ 3072,
315
+ 3200,
316
+ 3328,
317
+ 3456,
318
+ 3584,
319
+ 3712,
320
+ 3840,
321
+ 3968,
322
+ 4096,
323
+ ]
324
+ _n2: Union[int, List[int]] = [*range(1, 65535 + 1)]
325
+ _r2: Union[int, List[int]] = [*range(1, 1023 + 1)]
326
+
327
+ # Limits
328
+ """ Internal limits """
329
+ _vco_min = 1e6 # uses external VCO limits need to be set by the user
330
+ _vco_max = 4500e6
331
+ pfd_max = 167e6
332
+ vcxo_min = 1e6
333
+ vcxo_max = 500e6
334
+
335
+ minimize_feedback_dividers = False
336
+
337
+ # State management
338
+ _clk_names: List[str] = []
339
+
340
+ @property
341
+ def vco_min(self) -> float:
342
+ """Actual lower VCO frequency.
343
+
344
+ Valid range 1->4500 MHz
345
+
346
+ Returns:
347
+ float: Current vco minimum value
348
+ """
349
+ return self._vco_min
350
+
351
+ @vco_min.setter
352
+ def vco_min(self, value: float) -> None:
353
+ """Actual lower VCO frequency.
354
+
355
+ Valid range 1->4500 MHz
356
+
357
+ Args:
358
+ value (float): Allowable values for vco min
359
+
360
+ """
361
+ self._vco_min = value
362
+
363
+ @property
364
+ def vco_max(self) -> float:
365
+ """Actual upper VCO frequency.
366
+
367
+ Valid range 1->4500 MHz
368
+
369
+ Returns:
370
+ float: Current vco minimum value
371
+ """
372
+ return self._vco_max
373
+
374
+ @vco_max.setter
375
+ def vco_max(self, value: float) -> None:
376
+ """Actual upper VCO frequency.
377
+
378
+ Valid range 1->4500 MHz
379
+
380
+ Args:
381
+ value (float): Allowable values for vco min
382
+
383
+ """
384
+ self._vco_max = value
385
+
386
+ @property
387
+ def d(self) -> Union[int, List[int]]:
388
+ """Output dividers.
389
+
390
+ Valid dividers are 1,2,3,4,5,6..32->(even)->4096
391
+
392
+ Returns:
393
+ int: Current allowable dividers
394
+ """
395
+ return self._d
396
+
397
+ @d.setter
398
+ def d(self, value: Union[int, List[int]]) -> None:
399
+ """Output dividers.
400
+
401
+ Valid dividers are 1,2,3,4,5,6..32->(even)->4096
402
+
403
+ Args:
404
+ value (int, list[int]): Allowable values for divider
405
+
406
+ """
407
+ self._check_in_range(value, self.d_available, "d")
408
+ self._d = value
409
+
410
+ @property
411
+ def n2(self) -> Union[int, List[int]]:
412
+ """n2: VCO feedback divider.
413
+
414
+ Valid dividers are 1->65536
415
+
416
+ Returns:
417
+ int: Current allowable dividers
418
+ """
419
+ return self._n2
420
+
421
+ @n2.setter
422
+ def n2(self, value: Union[int, List[int]]) -> None:
423
+ """VCO feedback divider.
424
+
425
+ Valid dividers are 1->65536
426
+
427
+ Args:
428
+ value (int, list[int]): Allowable values for divider
429
+
430
+ """
431
+ self._check_in_range(value, self.n2_available, "n2")
432
+ self._n2 = value
433
+
434
+ @property
435
+ def r2(self) -> Union[int, List[int]]:
436
+ """VCXO input dividers.
437
+
438
+ Valid dividers are 1->4096
439
+
440
+ Returns:
441
+ int: Current allowable dividers
442
+ """
443
+ return self._r2
444
+
445
+ @r2.setter
446
+ def r2(self, value: Union[int, List[int]]) -> None:
447
+ """VCXO input dividers.
448
+
449
+ Valid dividers are 1->4096
450
+
451
+ Args:
452
+ value (int, list[int]): Allowable values for divider
453
+
454
+ """
455
+ self._check_in_range(value, self.r2_available, "r2")
456
+ self._r2 = value
457
+
458
+ def get_config(self, solution: CpoSolveResult = None) -> Dict:
459
+ """Extract configurations from solver results.
460
+
461
+ Collect internal clock chip configuration and output clock definitions
462
+ leading to connected devices (converters, FPGAs)
463
+
464
+ Args:
465
+ solution (CpoSolveResult): CPlex solution. Only needed for CPlex solver
466
+
467
+ Returns:
468
+ Dict: Dictionary of clocking rates and dividers for configuration
469
+
470
+ Raises:
471
+ Exception: If solver is not called first
472
+ """
473
+ if not self._clk_names:
474
+ raise Exception("set_requested_clocks must be called before get_config")
475
+
476
+ if solution:
477
+ self.solution = solution
478
+
479
+ out_dividers = [self._get_val(x) for x in self.config["out_dividers"]]
480
+
481
+ clk: float = (
482
+ self.vcxo # type: ignore # noqa: B950
483
+ * self._get_val(self.config["n2"]) # type: ignore # noqa: B950
484
+ / self._get_val(self.config["r2"]) # type: ignore # noqa: B950
485
+ )
486
+
487
+ config: Dict = {
488
+ "r2": self._get_val(self.config["r2"]),
489
+ "n2": self._get_val(self.config["n2"]),
490
+ "VCO": clk,
491
+ "vcxo": self.vcxo,
492
+ "out_dividers": out_dividers,
493
+ "output_clocks": [],
494
+ }
495
+
496
+ output_cfg = {}
497
+ for i, div in enumerate(out_dividers):
498
+ rate = clk / div # type: ignore # noqa: B950
499
+ output_cfg[self._clk_names[i]] = {"rate": rate, "divider": div}
500
+
501
+ config["output_clocks"] = output_cfg
502
+
503
+ self._saved_solution = config
504
+
505
+ return config
506
+
507
+ def _setup_solver_constraints(self, vcxo: int) -> None:
508
+ """Apply constraints to solver model.
509
+
510
+ Args:
511
+ vcxo (int): VCXO frequency in hertz
512
+ """
513
+ self.vcxo = vcxo
514
+ self.config = {
515
+ "r2": self._convert_input(self._r2, "r2"),
516
+ "n2": self._convert_input(self._n2, "n2"),
517
+ }
518
+ # self.config = {"r2": self.model.Var(integer=True, lb=1, ub=4095, value=1)}
519
+ # self.config["n2"] = self.model.Var(
520
+ # integer=True, lb=8, ub=4095
521
+ # ) # FIXME: CHECK UB
522
+
523
+ # PLL2 equations
524
+ self._add_equation(
525
+ [
526
+ vcxo / self.config["r2"] <= self.pfd_max,
527
+ vcxo / self.config["r2"] * self.config["n2"] <= self.vco_max,
528
+ vcxo / self.config["r2"] * self.config["n2"] >= self.vco_min,
529
+ ]
530
+ )
531
+
532
+ # Objectives
533
+ if self.minimize_feedback_dividers:
534
+ self.model.minimize(self.config["r2"])
535
+ # self.model.Obj(self.config["r2"])
536
+
537
+ def _setup(self, vcxo: int) -> None:
538
+ # Setup clock chip internal constraints
539
+
540
+ # FIXME: ADD SPLIT m1 configuration support
541
+
542
+ # Setup clock chip internal constraints
543
+ self._setup_solver_constraints(vcxo)
544
+
545
+ # Add requested clocks to output constraints
546
+ self.config["out_dividers"] = []
547
+ self._clk_names = [] # Reset
548
+
549
+ def _get_clock_constraint(
550
+ self, clk_name: List[str]
551
+ ) -> Union[int, float, CpoExpr, GK_Intermediate]:
552
+ """Get abstract clock output.
553
+
554
+ Args:
555
+ clk_name (str): String of clock name
556
+
557
+ Returns:
558
+ (int or float or CpoExpr or GK_Intermediate): Abstract
559
+ or concrete clock reference
560
+
561
+ Raises:
562
+ Exception: Invalid solver
563
+ """
564
+ if self.solver == "gekko":
565
+ __d = self._d if isinstance(self._d, list) else [self._d]
566
+
567
+ if __d.sort() != self.d_available.sort():
568
+ raise Exception("For solver gekko d is not configurable for LTC6952")
569
+ # Since d is so disjoint it is very annoying to solve.
570
+ mp = self.model.Var(integer=True, lb=1, ub=32)
571
+ nx = self.model.Var(integer=True, lb=0, ub=7)
572
+ od = self.model.Intermediate(mp * pow(2, nx))
573
+ elif self.solver == "CPLEX":
574
+ od = self._convert_input(self._d, "d_" + str(clk_name))
575
+ else:
576
+ raise Exception("Unknown solver {}".format(self.solver))
577
+
578
+ self.config["out_dividers"].append(od)
579
+ self._clk_names.append(clk_name)
580
+ return self.vcxo / self.config["r2"] * self.config["n2"] / od
581
+
582
+ def set_requested_clocks(
583
+ self, vcxo: int, out_freqs: List, clk_names: List[str]
584
+ ) -> None:
585
+ """Define necessary clocks to be generated in model.
586
+
587
+ Args:
588
+ vcxo (int): VCXO frequency in hertz
589
+ out_freqs (List): list of required clocks to be output
590
+ clk_names (List[str]): list of strings of clock names
591
+
592
+ Raises:
593
+ Exception: If len(out_freqs) != len(clk_names)
594
+ """
595
+ if len(clk_names) != len(out_freqs):
596
+ raise Exception("clk_names is not the same size as out_freqs")
597
+
598
+ # Setup clock chip internal constraints
599
+ self._setup(vcxo)
600
+ self._clk_names = clk_names
601
+
602
+ # Add requested clocks to output constraints
603
+ for out_freq in out_freqs:
604
+ if self.solver == "gekko":
605
+ __d = self._d if isinstance(self._d, list) else [self._d]
606
+ if __d.sort() != self.d_available.sort():
607
+ raise Exception(
608
+ "For solver gekko d is not configurable for LTC6952"
609
+ )
610
+
611
+ mp = self.model.Var(integer=True, lb=1, ub=32)
612
+ nx = self.model.Var(integer=True, lb=0, ub=7)
613
+ od = self.model.Intermediate(mp * pow(2, nx))
614
+
615
+ elif self.solver == "CPLEX":
616
+ od = self._convert_input(self._d, "d_" + str(out_freq))
617
+
618
+ self._add_equation(
619
+ [self.vcxo / self.config["r2"] * self.config["n2"] / od == out_freq]
620
+ )
621
+ self.config["out_dividers"].append(od)
622
+
623
+ # Objectives
624
+ # self.model.Obj(-1*eo) # Favor even dividers