pychopmarg.utility
Note: All submodule members are accessible, via: from pychopmarg.utility import ...
filter
Filtering utilities for PyChOpMarg.
Original author: David Banas <capn.freako@gmail.com>
Original date: March 3, 2024
Copyright (c) 2024 David Banas; all rights reserved World wide.
- pychopmarg.utility.filter.from_dB(x: float) float[source]
Convert from (dB) to real, assuming square law applies.
- pychopmarg.utility.filter.calc_Hctle(f: ndarray[Any, dtype[Real]], fz: float, fp1: float, fp2: float, fLF: float, gDC: float, gDC2: float) ndarray[Any, dtype[Comp]][source]
Return the voltage transfer function, H(f), of the Rx CTLE, according to (93A-22).
- Parameters:
f – Frequencies at which to calculate
Hctle(Hz).fz – First stage zero frequency (Hz).
fp1 – First stage lower pole frequency (Hz).
fp2 – First stage upper pole frequency (Hz).
fLF – Second stage pole/zero frequency (Hz).
gDC – First stage d.c. gain (dB).
gDC2 – Second stage d.c. gain (dB).
- Returns:
The complex voltage transfer function, H(f), for the CTLE.
- pychopmarg.utility.filter.calc_Hffe(freqs: ndarray[Any, dtype[Real]], td: float, tap_weights: ndarray[Any, dtype[Real]], n_post: int, hasCurs: bool = False) ndarray[Any, dtype[Comp]][source]
Calculate the voltage transfer function, H(f), for a digital FFE, according to (93A-21).
- Parameters:
freqs – Frequencies at which to calculate
Hffe(Hz).td – Tap delay time (s).
tap_weights – The filter tap weights.
n_post – The number of post-cursor taps.
- Keyword Arguments:
hasCurs –
tap_weightsincludes the cursor tap weight when True. Default: False (Cursor tap weight will be calculated.)- Returns:
The complex voltage transfer function, H(f), for the FFE.
The simple expression being returned is defended, as follows:
Take axiomatically that what we want to return is the sum of the rows of the following matrix:
\[\begin{split}\begin{bmatrix} b_0 e^{-j 2 \pi T 0 f_0} & b_0 e^{-j 2 \pi T 0 f_1} & b0 e^{-j 2 \pi T 0 f_2} ... \\ b_1 e^{-j 2 \pi T 1 f_0} & b_1 e^{-j 2 \pi T 1 f_1} & b1 e^{-j 2 \pi T 1 f_2} ... \\ b_2 e^{-j 2 \pi T 2 f_0} & b_2 e^{-j 2 \pi T 2 f_1} & b2 e^{-j 2 \pi T 2 f_2} ... \\ \vdots \end{bmatrix}\end{split}\]Now, note that each columnar sum is a dot product of the vectors:
\(\{b_n\}\), and
\(\{e^{-j 2 \pi n T \cdot f_m}\}\), where:
\(f_m = m \Delta f = \frac{m}{NT}\), giving:
\[H(f) = [ b_0, b_1, b_2, ... ] e^{-j 2 \pi T \mathbf{F}}\]where:
\[\begin{split}\mathbf{F} = \begin{bmatrix} f0 \cdot 0 & f1 \cdot 0 & f2 \cdot 0 ... \\ f0 \cdot 1 & f1 \cdot 1 & f2 \cdot 1 ... \\ f0 \cdot 2 & f1 \cdot 2 & f2 \cdot 2 ... \\ \vdots \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \\ 2 \\ \vdots \end{bmatrix} [f_0, f_1, f_2, ...] = \mathbf{n}^T \mathbf{f}\end{split}\]giving:
\[H(f) = \mathbf{b} e^{-j 2 \pi T \mathbf{n}^T \mathbf{f}}\]Finally, comparing the final expression above to the Python code reveals a match:
return bs @ np.exp(np.outer(np.arange(len(bs)), -1j * TWOPI * td * freqs))
Note that F may be pre-calculated, and needn’t be recalculated, once the system time/frequency vectors have been established. Doing so yields a significant performance improvement in cases with many Tx FFE combinations.
- pychopmarg.utility.filter.calc_Hdfe(freqs: ndarray[Any, dtype[Real]], td: float, tap_weights: ndarray[Any, dtype[Real]]) ndarray[Any, dtype[Comp]][source]
Calculate the voltage transfer function, H(f), for a Decision Feedback Equalizer (DFE).
- Parameters:
freqs – Frequencies at which to calculate
Hdfe(Hz).td – Tap delay time (s).
tap_weights – The vector of filter tap weights.
- Returns:
The complex voltage transfer function, H(f), for the DFE.
- pychopmarg.utility.filter.null_filter(nTaps: int, nPreTaps: int = 0) ndarray[Any, dtype[Real]][source]
Construct a null filter w/
nTapstaps and (optionally)nPreTapspre-cursor taps.- Parameters:
nTaps – Total number of taps, including the cursor tap.
- Keyword Arguments:
nPreTaps – Number of pre-cursor taps. Default: 0
- Returns:
The filter tap weight vector, including the cursor tap weight.
- pychopmarg.utility.filter.raised_cosine(x: ndarray[Any, dtype[Comp]]) ndarray[Any, dtype[Comp]][source]
Apply raised cosine window to input.
- pychopmarg.utility.filter.calc_H21(freqs: ndarray[Any, dtype[Real]], s2p: Network, g1: float, g2: float) ndarray[Any, dtype[Comp]][source]
Return the voltage transfer function, H21(f), of a terminated two port network, according to (93A-18).
- Parameters:
freqs – Frequencies at which to calculate the response (Hz).
s2p – Two port network of interest.
g1 – Reflection coefficient looking out of the left end of the channel.
g2 – Reflection coefficient looking out of the right end of the channel.
- Returns:
Complex voltage transfer function at given frequencies.
- Raises:
ValueError – If given network is not two port.
general
General purpose utilities for PyChOpMarg.
Original author: David Banas <capn.freako@gmail.com>
Original date: March 3, 2024
Copyright (c) 2024 David Banas; all rights reserved World wide.
- pychopmarg.utility.general.all_combs(xss: list[list[T]]) list[list[T]][source]
Generate all combinations of input.
- Parameters:
xss – The lists of candidates for each position in the final output.
- Returns:
All possible combinations of inputs.
- pychopmarg.utility.general.mk_combs(trips: list[tuple[float, float, float]]) list[ndarray[Any, dtype[Real]]][source]
Make all possible combinations of tap weights, given a list of “(min, max, step)” triples.
- Parameters:
trips – A list of “(min, max, step)” triples, one per weight.
- Returns:
A list of NDArrays of tap weights, including all possible combinations.
- pychopmarg.utility.general.from_irfft(x: ndarray[Any, dtype[Real]], t_irfft: ndarray[Any, dtype[Real]], t: ndarray[Any, dtype[Real]], nspui: int) ndarray[Any, dtype[Real]][source]
Interpolate
irfft()output totand subsample at fBaud.- Parameters:
x –
irfft()results to be interpolated and subsampled.t_irfft – Time index vector for
x.t – Desired new time index vector (same units as
t_irfft).nspui – Number of samples per unit interval in
t.
- Returns:
Interpolated and subsampled vector.
- Raises:
IndexError – If length of input doesn’t match length of
t_irfftvector.
Notes
1. Input vector is shifted, such that its peak occurs at
0.1 * max(t), before interpolating. This is done to:ensure that we don’t omit any non-causal behavior, which ends up at the end of an IFFT output vector when the peak is very near the beginning, and
to ensure that the majority of our available time span is available for capturing reflections.
The sub-sampling phase is adjusted, so as to ensure that we catch the peak.
- pychopmarg.utility.general.print_taps(ws: list[float]) str[source]
Return formatted tap weight values.
- pychopmarg.utility.general.fwhm(pr: ndarray[Any, dtype[Real]]) float[source]
Measure the full width at half maximum of the given pulse response.
- Parameters:
pr – Pulse response to measure.
- Returns:
Full width at half max of largest peak in given signal.
- Return type:
fwhm
Notes
Used to characterize the _bandwidth_ of a given channel.
- pychopmarg.utility.general.reflectivity(pr: ndarray[Any, dtype[Real]]) float[source]
Measure the _reflectivity_ of a channel with the given pulse response.
- Parameters:
pr – Pulse response of channel.
- Returns:
Reflectivity of channel.
- Return type:
ref
Notes
Use sum of: delta-x weighted by power at delta-x.
- pychopmarg.utility.general.get_channel_sets(path: Path) dict[str, list[dict[str, list[Path]]]][source]
Return all available groups of channel sets in the given path.
- Parameters:
path – The folder in which to begin searching. (Assumed to contain some number of sub-directories, in which the actual channel sets are contained.)
- Returns:
Dictionary of channel groups, each containing a list of channel sets.
Notes
- A “channel set” is a dictionary containing a thru channel and some number
of NEXT and FEXT aggressors.
probability
Statistical utilities for PyChOpMarg.
Original author: David Banas <capn.freako@gmail.com>
Original date: March 3, 2024
Copyright (c) 2024 David Banas; all rights reserved World wide.
- pychopmarg.utility.probability.filt_pr_samps(pr_samps: ndarray[Any, dtype[Real]], As: float, rel_thresh: float = 0.001) ndarray[Any, dtype[Real]][source]
Filter a list of pulse response samples for minimum magnitude.
- Parameters:
pr_samps – The pulse response samples to filter.
As – Signal amplitude, as per 93A.1.6.c.
- Keyword Arguments:
rel_thresh – Filtration threshold (As). Default: 0.001 (i.e. - 0.1%, as per Note 2 of 93A.1.7.1)
- Returns:
The subset of
pr_sampspassing filtration.
- pychopmarg.utility.probability.delta_pmf(h_samps: ndarray[Any, dtype[Real]], L: int = 4, curs_ix: int | None = None, y: ndarray[Any, dtype[Real]] | None = None, dbg_dict: Dict[str, Any] | None = None) tuple[ndarray[Any, dtype[Real]], ndarray[Any, dtype[Real]]][source]
Calculate the “delta-pmf” for a set of pulse response samples, as per (93A-40).
- Parameters:
h_samps – Vector of pulse response samples.
- Keyword Arguments:
L – Number of modulation levels. Default: 4
curs_ix – Cursor index override. Default: None (Means use argmax() to find cursor.)
y – y-values override vector. Default: None (Means calculate appropriate y-value vector here.)
dbg_dict – Optional dictionary into which debugging values may be stashed, for later analysis. Default: None
- Returns:
A pair consisting of
the voltages corresponding to the bins, and
their probabilities.
- Raises:
ValueError – If the given pulse response contains any NaNs.
ValueError – If a needed shift exceeds half the result vector length.
Notes
1. The input set of pulse response samples is filtered, as per Note 2 of 93A.1.7.1, unless a y-values override vector is provided, in which case it is assumed that the caller has already done the filtering.
- pychopmarg.utility.probability.calc_hJ(pulse_resp: ndarray[Any, dtype[Real]], As: float, cursor_ix: int, nspui: int, rel_thresh: float = 0.001) ndarray[Any, dtype[Real]][source]
Calculate the set of slopes for valid pulse response samples.
- Parameters:
pulse_resp – The pulse response of interest.
As – Signal amplitude, as per 93A.1.6.c.
cursor_ix – Cursor index.
nspui – Number of samples per UI.
- Keyword Arguments:
rel_thresh – Filtration threshold (As). Default: 0.001 (i.e. - 0.1%, as per Note 2 of 93A.1.7.1)
- Returns:
The calculated slopes around the valid samples.
- pychopmarg.utility.probability.loc_curs(pulse_resp: ndarray[Any, dtype[Real]], nspui: int, dfe_max: ndarray[Any, dtype[Real]], dfe_min: ndarray[Any, dtype[Real]], max_range: int = 1, eps: float = 0.001) int[source]
Locate the cursor position for the given pulse response, according to (93A-25) and (93A-26) (i.e. - Muller-Mueller criterion).
- Parameters:
pulse_resp – The pulse response of interest.
nspui – Number of samples per UI.
dfe_max – Vector of maximum DFE tap weight values.
dfe_min – Vector of minimum DFE tap weight values.
- Keyword Arguments:
max_range – The search radius, from the peak (UI). Default: 1
eps – Threshold for declaring floating point value to be zero. Default: 0.001
- Returns:
The index in the given pulse response vector of the cursor.
Notes
1. As per v3.70 of the COM MATLAB code, we only minimize the residual of (93A-25); we don’t require solving it exactly. (We do, however, give priority to exact solutions.)
sparams
S-parameter utilities for PyChOpMarg.
Original author: David Banas <capn.freako@gmail.com>
Original date: March 3, 2024
Copyright (c) 2024 David Banas; all rights reserved World wide.
- pychopmarg.utility.sparams.sdd_21(ntwk: Network, norm: float = 0.5, renumber: bool = False) Network[source]
Given a 4-port single-ended network, return its differential throughput as a 2-port network.
- Parameters:
ntwk – 4-port single ended network.
- Keyword Arguments:
norm – Normalization factor. (Default = 0.5)
renumber – Automatically detect and correct through path when True. Default: False
- Returns:
Sdd (2-port).
Notes
A “1->2/3->4” port ordering convention is assumed when renumber is False.
Automatic renumbering should not be used unless a solid d.c. thru path exists.
- pychopmarg.utility.sparams.se2mm(ntwk: Network, norm: float = 0.5, renumber: bool = False) Network[source]
Given a 4-port single-ended network, return its mixed mode equivalent in the following format:
\[\begin{split}\begin{bmatrix} Sdd11 & Sdd12 & Sdc11 & Sdc12 \\ Sdd21 & Sdd22 & Sdc21 & Sdc22 \\ Scd11 & Scd12 & Scc11 & Scc12 \\ Scd21 & Scd22 & Scc21 & Scc22 \end{bmatrix}\end{split}\]- Parameters:
ntwk – 4-port single ended network.
- Keyword Arguments:
norm – Normalization factor. (Default = 0.5)
renumber – Automatically detect and correct through path when True. Default: False
- Returns:
Mixed mode equivalent network.
Notes
A “1->2/3->4” port ordering convention is assumed when renumber is False.
Automatic renumbering should not be used unless a solid d.c. thru path exists.
- pychopmarg.utility.sparams.import_s32p(filename: Path, vic_chnl: int = 1) list[tuple[Network, str]][source]
Read in a 32-port Touchstone file, and return an equivalent list of 8 2-port differential networks: a single victim through channel and 7 crosstalk aggressors, according to the VITA 68.2 convention.
- Parameters:
filename – Name of Touchstone file to read in.
- Keyword Arguments:
vic_chnl – Victim channel number (from 1). Default = 1
- Returns:
a 2-port network representing a differential channel, and
the type of that channel, one of: ‘THRU’, ‘NEXT’, or ‘FEXT. (First element is the victim and the only one of type ‘THRU’.)
- Return type:
List of 8 pairs, each consisting of
- Raises:
ValueError – If Touchstone file is not 32-port.
Notes
Input Touchstone file is assumed single-ended.
The differential through and xtalk channels are returned.
Port 2 of all returned channels correspond to the same physical circuit node, typically, the Rx input node.
- pychopmarg.utility.sparams.sCshunt(freqs: ndarray[Any, dtype[Real]], c: float, r0: float = 50.0) Network[source]
Calculate the 2-port network for a shunt capacitance.
- Parameters:
freqs – The frequencies at which to calculate network data (Hz).
c – The capacitance (F).
- Keyword Arguments:
r0 – The reference impedance for the network (Ohms). Default: 50 Ohms.
- Returns:
The network corresponding to a shunt capacitance,
c, calculated at the given frequencies,freqs.
- pychopmarg.utility.sparams.sLseries(freqs: ndarray[Any, dtype[Real]], inductance: float, r0: float = 50.0) Network[source]
Calculate the 2-port network for a series inductance.
- Parameters:
freqs – The frequencies at which to calculate network data (Hz).
inductance – The inductance (H).
- Keyword Arguments:
r0 – The reference impedance for the network (Ohms). Default: 50 Ohms.
- Returns:
The network corresponding to a series inductance,
inductance, calculated at the given frequencies,freqs.
- pychopmarg.utility.sparams.sDieLadderSegment(freqs: ndarray[Any, dtype[Real]], trip: tuple[float, float, float]) Network[source]
Calculate one segment of the on-die parasitic ladder network.
- Parameters:
f – List of frequencies to use for network creation (Hz).
trip –
Triple containing:
R0: Reference impedance for network (Ohms).
Cd: Shunt capacitance (F).
Ls: Series inductance (H).
- Returns:
Two port network for segment.
- pychopmarg.utility.sparams.sPkgTline(f: ndarray[Any, dtype[Real]], r0: float, a1: float, a2: float, tau: float, gamma0: float, z_pairs: list[tuple[float, float]]) Network[source]
Return the 2-port network corresponding to a package transmission line, according to (93A-9:14).
- Parameters:
f – Frequencies at which to calculate S-parameters (Hz).
r0 – System reference impedance (Ohms).
a1 – First polynomial coefficient (sqrt_ns/mm).
a2 – Second polynomial coefficient (ns/mm).
tau – Propagation delay (ns/mm).
gamma0 – Propagation loss constant (1/mm).
z_pairs –
List of pairs defining the T-line segments, each containing:
zc: Characteristic impedance of segment (Ohms).
zp: Length of segment (mm).
- Returns:
2-port network equivalent to package transmission line.
- pychopmarg.utility.sparams.s2p_pulse_response(s2p: Network, ui: float, t: ndarray[Any, dtype[Real]] | None = None) tuple[ndarray[Any, dtype[Real]], ndarray[Any, dtype[Real]]][source]
Calculate the __pulse__ response of a 2-port network, using the SciKit-RF provided __step__ response.
- Parameters:
s2p – The 2-port network to use.
ui – The unit interval (s).
- Keyword Arguments:
t – Optional time vector for use in interpolating the resultant pulse response (s). Default: None (Use time vector returned by __SciKit-RF__ step response function.)
- Returns:
A pair consisting of:
The time values at which the pulse response has been sampled, and
The real-valued pulse response samples of the given 2-port network.
- Return type:
t, p
- Raises:
ValueError – If given network is not 2-port.