mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
mpm: x440: add fabric resampling to clock policy
Adjusting the MPM code to enable the correct generation of data_clk and data_clk_2x based on the fabric resampler rate. Further increasing the rfdc_clocks to match the desired higher sampling rates of the RFDC.
This commit is contained in:
parent
94dd1084f8
commit
4bf834a9a8
@ -464,7 +464,7 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
def _read_converter_rates(self):
|
||||
"""Gets the converter rate.
|
||||
|
||||
Gets the converter rate from the argument string, if it is given there,
|
||||
Gets the converter rate from the argument string, if it is given there,
|
||||
None otherwise.
|
||||
"""
|
||||
self.conv_rates = self.args.get("converter_rate")
|
||||
@ -545,14 +545,14 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
# Calculate desired converter rate: If a converter rate was passed, check if
|
||||
# we can decimate from converter rate to master clock rate and if this converter rate
|
||||
# is within the valid range. If this is impossible, pick the converter rate automatically.
|
||||
div = desired_conv_rate / desired_mcr
|
||||
coerced_mcr = desired_mcr
|
||||
coerced_mcr = desired_mcr * self._extra_resampling
|
||||
div = desired_conv_rate / coerced_mcr
|
||||
if (
|
||||
div not in X4xxRfdcCtrl.RFDC_RESAMPLER
|
||||
or not X4xxRfdcCtrl.CONV_RATE_MIN <= desired_conv_rate <= X4xxRfdcCtrl.CONV_RATE_MAX
|
||||
or desired_mcr not in MCR_LMK_VCO
|
||||
or coerced_mcr not in MCR_LMK_VCO
|
||||
):
|
||||
coerced_mcr = min(sorted(MCR_LMK_VCO), key=lambda x: abs(x - desired_mcr))
|
||||
coerced_mcr = min(sorted(MCR_LMK_VCO), key=lambda x: abs(x - coerced_mcr))
|
||||
for div in sorted(X4xxRfdcCtrl.RFDC_RESAMPLER, reverse=True):
|
||||
if coerced_mcr * div <= X4xxRfdcCtrl.CONV_RATE_MAX:
|
||||
break
|
||||
@ -682,6 +682,14 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
if len(master_clock_rates) < self.get_num_rates():
|
||||
master_clock_rates = [master_clock_rates[0]] * self.get_num_rates()
|
||||
|
||||
# In case resamplers are present there is only 1 MCR allowed
|
||||
if len(master_clock_rates) > 1 and self._extra_resampling > 1:
|
||||
if master_clock_rates[0] != master_clock_rates[1]:
|
||||
raise ValueError(
|
||||
"X440 with resamplers only supports identical "
|
||||
"master clock rates on both DBs."
|
||||
)
|
||||
|
||||
# Check if MCR meets BW
|
||||
for mcr in master_clock_rates:
|
||||
if not self._get_min_mcr() <= mcr <= self._get_max_mcr():
|
||||
@ -695,6 +703,8 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
conv_rates = []
|
||||
for idx, mcr in enumerate(master_clock_rates):
|
||||
conv_rate = 0 if self.conv_rates is None else self.conv_rates[idx]
|
||||
# If extra_resampling is >1, then from this place on, mcr will be
|
||||
# the MCR multiplied by the extra resampling factor in the PL.
|
||||
mcr, cvr = self._match_mcrs(mcr, conv_rate)
|
||||
mcrs.append(mcr)
|
||||
conv_rates.append(cvr)
|
||||
@ -707,7 +717,7 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
conv_rates[1] = conv_rates[0]
|
||||
|
||||
# With these values check if we can do this in MMCM
|
||||
rfdc_rate = list(map(lambda x: int(x / (self._spc * self._extra_resampling)), mcrs))
|
||||
rfdc_rate = [int(x / self._spc) for x in mcrs]
|
||||
min_mmcm_vco_rate = lcm(rfdc_rate[0], rfdc_rate[1])
|
||||
# Inform user if we don't have an exact match
|
||||
if min_mmcm_vco_rate > X4xxRfdcCtrl.MMCM_VCO_MAX:
|
||||
@ -715,10 +725,11 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
# Ensure we're falling back to converter rate 0, too
|
||||
conv_rates[1] = conv_rates[0]
|
||||
|
||||
if mcrs != master_clock_rates:
|
||||
if mcrs != [mcr * self._extra_resampling for mcr in master_clock_rates]:
|
||||
self.log.warning(
|
||||
f"Unable to use desired master clock rate(s), using "
|
||||
f"{mcrs[0]/1e6} MHz for DB0 and {mcrs[1]/1e6} MHz for DB1."
|
||||
f"{mcrs[0]/self._extra_resampling/1e6} MHz for DB0 and "
|
||||
f"{mcrs[1]/self._extra_resampling/1e6} MHz for DB1."
|
||||
)
|
||||
if self.conv_rates is not None and self.conv_rates != conv_rates:
|
||||
self.log.warning(
|
||||
@ -726,16 +737,18 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
f"{conv_rates[0]/1e6} MSps for DB0 "
|
||||
f"and {conv_rates[1]/1e6} MSps for DB1. Converter rate needs "
|
||||
f"to be a {X4xxRfdcCtrl.RFDC_RESAMPLER} multiple of the master "
|
||||
f"clock rates {mcrs[0]/1e6} MHz and {mcrs[1]/1e6} MHz "
|
||||
f"clock rates {mcrs[0]/self._extra_resampling/1e6} MHz and "
|
||||
f"{mcrs[1]/self._extra_resampling/1e6} MHz multiplied by the "
|
||||
f"extra resampling factor {self._extra_resampling}, "
|
||||
f"but additional clock constraints may limit this."
|
||||
)
|
||||
self.conv_rates = conv_rates
|
||||
return mcrs
|
||||
return [mcr / self._extra_resampling for mcr in mcrs]
|
||||
|
||||
def get_config(self, ref_clock_freq, master_clock_rates):
|
||||
"""Returns a valid configuration based on the master clock rate.
|
||||
|
||||
It uses the configuration where the RFDC_CLOCK/SPC is the closest to the MCR
|
||||
It uses the configuration where the RFDC_CLOCK/SPC is the closest to the MCR.
|
||||
This method is called after coerce_mcr() has run and - if necessary -
|
||||
rounded the MCR values, so will skip the checks here to save some time.
|
||||
"""
|
||||
@ -747,6 +760,8 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
conv_rates = []
|
||||
for idx, mcr in enumerate(master_clock_rates):
|
||||
conv_rate = 0 if self.conv_rates is None else self.conv_rates[idx]
|
||||
# If extra_resampling is >1, then from this place on, mcr will be
|
||||
# the MCR multiplied by the extra resampling factor in the PL.
|
||||
mcr, cvr = self._match_mcrs(mcr, conv_rate)
|
||||
mcrs.append(mcr)
|
||||
conv_rates.append(cvr)
|
||||
@ -790,7 +805,7 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
conv_rate % sysref_config["SYSREF_FREQ"] == 0.0 for conv_rate in conv_rates
|
||||
), "Converter Rate is not a multiple of the SysRef freq"
|
||||
|
||||
rfdc_rate = list(map(lambda x: int(x / (self._spc * self._extra_resampling)), mcrs))
|
||||
rfdc_rate = list(map(lambda x: int(x / self._spc), mcrs))
|
||||
mmcm_input, mmcm_vco_rate = self._get_mmcm_rates(
|
||||
rfdc_rate, lmk_vco, sysref_config["SYSREF_FREQ"]
|
||||
)
|
||||
@ -799,7 +814,8 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
if not mmcm_input or mmcm_input > lmk_vco:
|
||||
error_msg = (
|
||||
f"Unable to find a valid MMCM configuration for Master Clock Rate(s) "
|
||||
f"{mcrs[0]/1e6} MHz and {mcrs[1]/1e6} MHz. Please choose different "
|
||||
f"{mcrs[0]/self._extra_resampling/1e6} MHz and "
|
||||
f"{mcrs[1]/self._extra_resampling/1e6} MHz. Please choose different "
|
||||
f"Master Clock Rate(s)."
|
||||
)
|
||||
self.log.error(error_msg)
|
||||
@ -857,6 +873,8 @@ class X440ClockPolicy(X4xxClockPolicy):
|
||||
"r0_clk_2x": r0_clk2x,
|
||||
"r1_clk_2x": r1_clk2x,
|
||||
"prc": prc_out_div,
|
||||
"data_clk": r0_clk * self._extra_resampling,
|
||||
"data_clk_2x": r0_clk2x * self._extra_resampling,
|
||||
},
|
||||
"rfdc_configs": [RfdcConfig(**rfdc_cfg0), RfdcConfig(**rfdc_cfg1)],
|
||||
"spll_config": SpllConfig(**spll_cfg),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user