Skip to content

Commit ef3621c

Browse files
committed
Add more tests for AD9084 and AD9088
Signed-off-by: Travis F. Collins <travis.collins@analog.com>
1 parent 55136ce commit ef3621c

4 files changed

Lines changed: 1253 additions & 0 deletions

File tree

tests/test_ad9084_combined.py

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
"""Tests for AD9084 combined RX+TX model."""
2+
3+
import pytest
4+
5+
import adijif
6+
from adijif.converters.ad9084 import ad9084, ad9084_rx, ad9084_tx
7+
8+
# ── Instantiation ────────────────────────────────────────────────────────────
9+
10+
11+
def test_ad9084_instantiation():
12+
"""Verify AD9084 combined model instantiates without error."""
13+
dev = ad9084(solver="CPLEX")
14+
assert dev is not None
15+
16+
17+
def test_ad9084_name():
18+
"""Verify AD9084 combined model has the expected name."""
19+
dev = ad9084(solver="CPLEX")
20+
assert dev.name == "AD9084"
21+
22+
23+
def test_ad9084_converter_type():
24+
"""Verify AD9084 combined model reports adc_dac converter type."""
25+
dev = ad9084(solver="CPLEX")
26+
assert dev.converter_type == "adc_dac"
27+
28+
29+
def test_ad9084_nested_attribute():
30+
"""Verify _nested lists both adc and dac."""
31+
dev = ad9084(solver="CPLEX")
32+
assert dev._nested == ["adc", "dac"]
33+
34+
35+
def test_ad9084_has_adc_sub_converter():
36+
"""Verify AD9084 combined model exposes an adc sub-converter."""
37+
dev = ad9084(solver="CPLEX")
38+
assert hasattr(dev, "adc")
39+
assert isinstance(dev.adc, ad9084_rx)
40+
41+
42+
def test_ad9084_has_dac_sub_converter():
43+
"""Verify AD9084 combined model exposes a dac sub-converter."""
44+
dev = ad9084(solver="CPLEX")
45+
assert hasattr(dev, "dac")
46+
assert isinstance(dev.dac, ad9084_tx)
47+
48+
49+
def test_ad9084_via_system():
50+
"""Verify AD9084 combined model can be created through the system factory."""
51+
sys = adijif.system(
52+
"ad9084", "hmc7044", "xilinx", 125000000, solver="CPLEX"
53+
)
54+
assert sys.converter.name == "AD9084"
55+
56+
57+
def test_ad9084_accessible_from_adijif():
58+
"""Verify ad9084 is exported at the adijif package level."""
59+
assert hasattr(adijif, "ad9084")
60+
assert adijif.ad9084 is ad9084
61+
62+
63+
# ── Sub-converter defaults ────────────────────────────────────────────────────
64+
65+
66+
def test_ad9084_adc_is_ad9084_rx():
67+
"""Verify the adc sub-converter is an AD9084_RX instance."""
68+
dev = ad9084(solver="CPLEX")
69+
assert dev.adc.name == "AD9084_RX"
70+
assert dev.adc.converter_type == "adc"
71+
72+
73+
def test_ad9084_dac_is_ad9084_tx():
74+
"""Verify the dac sub-converter is an AD9084_TX instance."""
75+
dev = ad9084(solver="CPLEX")
76+
assert dev.dac.name == "AD9084_TX"
77+
assert dev.dac.converter_type == "dac"
78+
79+
80+
def test_ad9084_clock_limits_match_rx():
81+
"""Verify combined model clock limits reflect the RX limits."""
82+
dev = ad9084(solver="CPLEX")
83+
assert dev.converter_clock_min == ad9084_rx.converter_clock_min
84+
assert dev.converter_clock_max == ad9084_rx.converter_clock_max
85+
86+
87+
# ── _get_converters ──────────────────────────────────────────────────────────
88+
89+
90+
def test_ad9084_get_converters_returns_two():
91+
"""Verify _get_converters returns both sub-converters."""
92+
dev = ad9084(solver="CPLEX")
93+
convs = dev._get_converters()
94+
assert len(convs) == 2
95+
96+
97+
def test_ad9084_get_converters_contains_adc_and_dac():
98+
"""Verify _get_converters list contains the adc and dac sub-converters."""
99+
dev = ad9084(solver="CPLEX")
100+
convs = dev._get_converters()
101+
assert dev.adc in convs
102+
assert dev.dac in convs
103+
104+
105+
# ── Clock names ──────────────────────────────────────────────────────────────
106+
107+
108+
def test_ad9084_clock_names_count():
109+
"""Verify get_required_clock_names returns three names."""
110+
dev = ad9084(solver="CPLEX")
111+
names = dev.get_required_clock_names()
112+
assert len(names) == 3
113+
114+
115+
def test_ad9084_clock_names_direct():
116+
"""Verify clock names under direct clocking use the dac_clock prefix."""
117+
dev = ad9084(solver="CPLEX")
118+
dev.adc.clocking_option = "direct"
119+
names = dev.get_required_clock_names()
120+
assert names[0] == "ad9084_dac_clock"
121+
assert names[1] == "ad9084_adc_sysref"
122+
assert names[2] == "ad9084_dac_sysref"
123+
124+
125+
def test_ad9084_clock_names_pll():
126+
"""Verify clock names under PLL clocking use the pll_ref prefix."""
127+
dev = ad9084(solver="CPLEX")
128+
dev.adc._clocking_option = "integrated_pll"
129+
names = dev.get_required_clock_names()
130+
assert names[0] == "ad9084_pll_ref"
131+
132+
133+
# ── validate_config ───────────────────────────────────────────────────────────
134+
135+
136+
def test_ad9084_validate_config_delegates_to_sub_converters():
137+
"""Verify validate_config calls through to both sub-converters.
138+
139+
Confirm that an error from either sub-converter propagates out of the
140+
combined validate_config, proving delegation rather than a no-op.
141+
"""
142+
dev = ad9084(solver="CPLEX")
143+
# Default TX state (mode "2", sample_clock 8 GHz) has a bit clock that
144+
# exceeds the JESD204C lane-rate limit, so validate_config must raise.
145+
with pytest.raises(Exception, match="bit clock"):
146+
dev.validate_config()
147+
148+
149+
# ── empty quick_configuration_modes ──────────────────────────────────────────
150+
151+
152+
def test_ad9084_quick_configuration_modes_empty():
153+
"""Verify combined model has empty quick_configuration_modes."""
154+
dev = ad9084(solver="CPLEX")
155+
assert dev.quick_configuration_modes == {}
156+
157+
158+
# ── Sub-converter independence ────────────────────────────────────────────────
159+
160+
161+
def test_ad9084_adc_sample_clock_settable():
162+
"""Verify the adc sub-converter sample clock can be modified."""
163+
dev = ad9084(solver="CPLEX")
164+
dev.adc.sample_clock = 1e9
165+
assert dev.adc.sample_clock == 1e9
166+
167+
168+
def test_ad9084_dac_sample_clock_settable():
169+
"""Verify the dac sub-converter sample clock can be modified."""
170+
dev = ad9084(solver="CPLEX")
171+
dev.dac.sample_clock = 2e9
172+
assert dev.dac.sample_clock == 2e9
173+
174+
175+
def test_ad9084_adc_mode_change_does_not_affect_dac():
176+
"""Verify changing the ADC JESD mode does not change the DAC mode."""
177+
dev = ad9084(solver="CPLEX")
178+
original_dac_L = dev.dac.L
179+
dev.adc.set_quick_configuration_mode("47", "jesd204c")
180+
assert dev.dac.L == original_dac_L
181+
182+
183+
def test_ad9084_dac_mode_change_does_not_affect_adc():
184+
"""Verify changing the DAC JESD mode does not change the ADC mode."""
185+
dev = ad9084(solver="CPLEX")
186+
original_adc_L = dev.adc.L
187+
dev.dac.set_quick_configuration_mode("2", "jesd204c")
188+
assert dev.adc.L == original_adc_L
189+
190+
191+
# ── System factory integration ────────────────────────────────────────────────
192+
193+
194+
def test_ad9084_system_has_nested_converters():
195+
"""Verify system created with ad9084 exposes _nested on the converter."""
196+
sys = adijif.system(
197+
"ad9084", "hmc7044", "xilinx", 125000000, solver="CPLEX"
198+
)
199+
assert sys.converter._nested == ["adc", "dac"]
200+
201+
202+
def test_ad9084_system_sub_converters_accessible():
203+
"""Verify adc and dac are accessible from the converter in a system context."""
204+
sys = adijif.system(
205+
"ad9084", "hmc7044", "xilinx", 125000000, solver="CPLEX"
206+
)
207+
assert isinstance(sys.converter.adc, ad9084_rx)
208+
assert isinstance(sys.converter.dac, ad9084_tx)
209+
210+
211+
def test_ad9084_system_full_solve():
212+
"""Verify a system with the ad9084 converter can solve without error."""
213+
sys = adijif.system(
214+
"ad9084", "hmc7044", "xilinx", 125000000, solver="CPLEX"
215+
)
216+
sys.fpga.setup_by_dev_kit_name("vcu118")
217+
218+
converter_rate = int(20e9)
219+
cddc_dec = 4
220+
fddc_dec = 2
221+
sys.converter.adc.sample_clock = converter_rate / (cddc_dec * fddc_dec)
222+
sys.converter.adc.datapath.cddc_decimations = [cddc_dec] * 4
223+
sys.converter.adc.datapath.fddc_decimations = [fddc_dec] * 8
224+
sys.converter.adc.datapath.fddc_enabled = [True] * 8
225+
sys.converter.adc.clocking_option = "direct"
226+
sys.add_pll_inline("adf4382", 125e6, sys.converter)
227+
# sys.add_pll_sysref("adf4030", 125e6, sys.converter, sys.fpga)
228+
229+
sys.converter.dac.sample_clock = converter_rate / (cddc_dec * fddc_dec)
230+
sys.converter.dac.datapath.cduc_interpolation = 4
231+
sys.converter.dac.clocking_option = "direct"
232+
# sys.add_pll_inline("adf4382", 125e6, sys.converter)
233+
# sys.add_pll_sysref("adf4030", 125e6, sys.converter, sys.fpga)
234+
235+
# JESD
236+
mode_rx = adijif.utils.get_jesd_mode_from_params(
237+
sys.converter.adc, M=4, L=8, S=1, Np=16, jesd_class="jesd204c"
238+
)
239+
assert mode_rx
240+
mode_rx = mode_rx[0]["mode"]
241+
sys.converter.adc.set_quick_configuration_mode(mode_rx, "jesd204c")
242+
mode_tx = adijif.utils.get_jesd_mode_from_params(
243+
sys.converter.dac, M=4, L=8, S=1, Np=16, jesd_class="jesd204c"
244+
)
245+
assert mode_tx
246+
mode_tx = mode_tx[0]["mode"]
247+
sys.converter.dac.set_quick_configuration_mode(mode_tx, "jesd204c")
248+
249+
cfg = sys.solve()
250+
251+
assert cfg is not None

0 commit comments

Comments
 (0)