pychopmarg.com
Functions
- pychopmarg.com.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 input lists.
- pychopmarg.com.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_weights includes 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.
- Raises:
None –
Classes
- class pychopmarg.com.COM(debug: bool = False)[source]
Encoding of the IEEE 802.3-22 Annex 93A/178A ‘Channel Operating Margin’ (COM) specification.
- Add = 0.05
- Afe = 0.4
- Ane = 0.6
- Ani = 0.0
- Av = 0.4
- Cb = 0.0
- Cd = [4e-14, 9e-14, 1.1e-13]
- Cp = 1.8e-13
- DER0 = 1e-05
- FB = 25781250000.0
- H(s2p: Network, tx_taps: ndarray[Any, dtype[Real]] | None = None, gDC: float | None = None, gDC2: float | None = None, rx_taps: ndarray[Any, dtype[Real]] | None = None, dfe_taps: ndarray[Any, dtype[Real]] | None = None, passive_RxFFE: bool = False) ndarray[Any, dtype[Comp]][source]
Return the voltage transfer function, H(f), of a complete COM signal path, according to (93A-19).
- Parameters:
s2p – Two port network of interest.
- Keyword Arguments:
tx_taps – Tx FFE tap weights. Default: None (i.e. - Use self.tx_taps.)
gDC – CTLE first stage d.c. gain (dB). Default: None (i.e. - Use self.gDC.)
gDC2 – CTLE second stage d.c. gain (dB). Default: None (i.e. - Use self.gDC2.)
rx_taps – Rx FFE tap weights. Default: None (i.e. - Use self.rx_taps.)
dfe_taps – Rx DFE tap weights. Default: None (i.e. - Use self.dfe_taps.)
passive_RxFFE – Enforce passivity of Rx FFE when True. Default: True
- Returns:
Complex voltage transfer function of complete path.
- Raises:
ValueError – If given network is not two port.
Notes
It is in this processing step that linear EQ is first applied.
- Any unprovided EQ values are taken from the COM instance.
If you really want to omit a particular EQ component then call with:
tx_taps/rx_taps: []
gDC/gDC2: 0
- H21(s2p: Network) ndarray[Any, dtype[Comp]][source]
Return the voltage transfer function, H21(f), of a terminated two port network, according to (93A-18).
- Parameters:
s2p – Two port network of interest.
- Returns:
Complex voltage transfer function at given frequencies.
- Raises:
ValueError – If given network is not two port.
Notes
- It is at this point in the analysis that the “raw” Touchstone data
gets interpolated to our system frequency vector.
- After this step, the package and R0/Rd mismatch have been accounted for,
but not the EQ.
- property Hctf: ndarray[Any, dtype[Comp]]
- property Hr: ndarray[Any, dtype[Comp]]
Return the voltage transfer function, H(f), of the Rx AFE, according to (93A-20).
- property Ht: ndarray[Any, dtype[Comp]]
Return the voltage transfer function, H(f), associated w/ the Tx risetime, according to (93A-46).
- L = 2
- Ls = [1.3e-10, 1.5e-10, 1.4e-10]
- N_DFE = 1
- R0 = 50.0
- RLM = 1.0
- Rd = 55.0
- TxSNR = 27.0
- property Xsinc: ndarray[Any, dtype[Real]]
Frequency domain sinc(f) corresponding to Rect(ui) in time domain.
- a1 = 0.00089
- a2 = 0.0002
- about_str = '\n <H2><em>PyChOpMarg</em> - A Python implementation of COM, as per IEEE 802.3-22 Annex 93A.</H2>\n\n <strong>By:</strong> David Banas <capn.freako@gmail.com><p>\n\n <strong>On:</strong> August 12, 2024<p>\n\n <strong>At:</strong> v1.1.3\n\n <H3>Useful Links</H3>\n\n (You\'ll probably need to: right click, select <em>Copy link address</em>, and paste into your browser.)\n <UL>\n\n <LI><a href="https://github.com/capn-freako/PyChOpMarg"><em>GitHub</em> Home</a>\n <LI><a href="https://pypi.org/project/PyChOpMarg/"><em>PyPi</em> Home</a>\n <LI><a href="https://readthedocs.org/projects/pychopmarg/"><em>Read the Docs</em> Home</a>\n </UL>\n '
- add_pkg(ntwk: tuple[Network, str]) tuple[Network, str][source]
Add package response to raw channel.
- add_pkgs(ntwks: list[tuple[Network, str]]) list[tuple[Network, str]][source]
Add package response to raw channels and generate pulse responses.
- bmax = [1.0]
- bmin = [-1.0]
- c0_min = 0.0
- calc_Hctf(gDC: float | None = None, gDC2: float | None = None) ndarray[Any, dtype[Comp]][source]
Return the voltage transfer function, H(f), of the Rx CTLE, according to (93A-22).
- Keyword Arguments:
gDC – CTLE first stage d.c. gain (dB). Default: None
gDC2 – CTLE second stage d.c. gain (dB). Default: None
Notes
- The instance’s current value(s) for gDC and gDC2 are used if not provided.
(Necessary, to accommodate sweeping when optimizing EQ.)
- calc_fom(tx_taps: ndarray[Any, dtype[Real]], gDC: float | None = None, gDC2: float | None = None, rx_taps: ndarray[Any, dtype[Real]] | None = None, opt_mode: OptMode | None = None, norm_mode: NormMode | None = None, unit_amp: bool | None = None) float[source]
Calculate the figure of merit (FOM), given the existing linear EQ settings. Optimize Rx FFE taps if they aren’t specified by caller.
- Parameters:
tx_taps – The Tx FFE tap weights, excepting the cursor. (The cursor takes whatever is left.)
- Keyword Arguments:
gDC – CTLE first stage d.c. gain. Default: None (i.e. - Use self.gDC.)
gDC2 – CTLE second stage d.c. gain. Default: None (i.e. - Use self.gDC2.)
rx_taps – Rx FFE tap weight overrides. Default: None (i.e. - Optimize Rx FFE tap weights.)
opt_mode – Optimization mode. Default: None (i.e. - Use self.opt_mode.) Note: Currently, unused; see ToDo #1, below.
norm_mode – The tap weight normalization mode to use. Default: None (i.e. - Use self.norm_mode.)
unit_amp – Enforce unit pulse response amplitude when True. (For comparing przf() results to mmse() results.) Default: None (i.e. - Use self.unit_amp.)
- Returns:
The resultant figure of merit.
- Raises:
None –
Notes
See: IEEE 802.3-2022 93A.1.6.
When not provided, the values for gDC and gDC2 are taken from the COM instance.
- Unlike other member functions of the
COMclass, this function _optimizes_ the Rx FFE tap weights when they are not provided.
- Unlike other member functions of the
Todo
Integrate MMSE, for less confusing code structure/flow.
- calc_hJ(pulse_resp: ndarray[Any, dtype[Real]], As: float, cursor_ix: 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.
- 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.
- calc_noise(cursor_ix: int | None = None, opt_mode: OptMode | None = None, norm_mode: NormMode | None = None, unit_amp: bool | None = None, dbg_dict: Dict[str, Any] = None) tuple[float, float, int][source]
Calculate the interference and noise for COM.
- Keyword Arguments:
cursor_ix – An optional predetermined cursor index, to be used instead of our own estimate. (In support of MMSE.) Default: None
opt_mode – Optimization mode. Default: None (i.e. - Use self.opt_mode.)
norm_mode – The tap weight normalization mode to use. Default: None (i.e. - Use self.norm_mode.)
unit_amp – Enforce unit pulse response amplitude when True. (For comparing przf() results to mmse() results.) Default: None (i.e. - Use self.unit_amp.)
dbg_dict – Optional dictionary into which debugging values may be stashed, for later analysis. Default: None
- Returns:
signal amplitude
noise + interference amplitude (V)
cursor location within victim pulse response vector
Notes
- Assumes the following instance variables have been set optimally:
gDC
gDC2
tx_taps
rx_taps
(This assumption is embedded into the gen_pulse_resps() function.)
Warns if 2*As/npts rises above 10 uV, against standard’s recommendation.
- calc_sZp(NEXT: bool = False) Network[source]
Return the 2-port network corresponding to a package transmission line, according to (93A-9:14).
- Keyword Arguments:
NEXT – Use first package T-line length option when True. Default: False
- Returns:
2-port network equivalent to package transmission line.
- chnl_s32p = PosixPath('.')
- chnl_s4p_fext1 = PosixPath('.')
- chnl_s4p_fext2 = PosixPath('.')
- chnl_s4p_fext3 = PosixPath('.')
- chnl_s4p_fext4 = PosixPath('.')
- chnl_s4p_fext5 = PosixPath('.')
- chnl_s4p_fext6 = PosixPath('.')
- chnl_s4p_next1 = PosixPath('.')
- chnl_s4p_next2 = PosixPath('.')
- chnl_s4p_next3 = PosixPath('.')
- chnl_s4p_next4 = PosixPath('.')
- chnl_s4p_next5 = PosixPath('.')
- chnl_s4p_next6 = PosixPath('.')
- chnl_s4p_thru = PosixPath('.')
- com = 0.0
- com_As = 0.0
- com_cursor_ix = 0
- com_dfe_taps = ' 0.00'
- com_sigma_G = 0.0
- com_sigma_N = 0.0
- com_sigma_Tx = 0.0
- debug = False
- dfe_taps = array([0.])
- eta0 = 5.2e-08
- fLF = 1000000.0
- fb = 25781250000.0
- 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_samps passing filtration.
- fmax = 40000000000.0
- fom = 0.0
- fom_As = 0.0
- fom_cursor_ix = 0
- fom_dfe_taps = ' 0.00'
- fom_tx_taps = ' 0.00 0.00 0.00 0.00 0.00 0.00'
- fp1 = 6445312500.0
- fp2 = 25781250000.0
- fr = 0.75
- property freqs: ndarray[Any, dtype[Real]]
System frequency vector (Hz); decoupled from system time vector!
- fstep = 10000000.0
- fz = 6445312500.0
- gDC = 0
- gDC2 = 0
- gDC2_vals = [0.0]
- gDC_vals = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12]
- gamma0 = 0.0005
- property gamma1: float
Reflection coefficient looking out of the left end of the channel.
- property gamma2: float
Reflection coefficient looking out of the right end of the channel.
- gen_pulse_resps(ntwks: list[tuple[Network, str]] | None = None, gDC: float | None = None, gDC2: float | None = None, tx_taps: ndarray[Any, dtype[Real]] | None = None, rx_taps: ndarray[Any, dtype[Real]] | None = None, dfe_taps: ndarray[Any, dtype[Real]] | None = None, apply_eq: bool = True) list[ndarray[Any, dtype[Real]]][source]
Generate pulse responses for all networks.
- Keyword Arguments:
ntwks – The list of networks to generate pulse responses for. Default: None (i.e. - Use self.chnls.)
gDC – Rx CTLE first stage d.c. gain. Default: None (i.e. - Use self.gDC.)
gDC2 – Rx CTLE second stage d.c. gain. Default: None (i.e. - Use self.gDC2.)
tx_taps – Desired Tx tap weights. Default: None (i.e. - Use self.tx_taps.)
rx_taps – Desired Rx FFE tap weights. Default: None (i.e. - Use self.rx_taps.)
dfe_taps – Desired Rx DFE tap weights. Default: None (i.e. - Use self.dfe_taps.)
apply_eq – Include linear EQ when True; otherwise, exclude it. (Allows for pulse response generation of terminated, but unequalized, channel.) Default: True
- Returns:
list of pulse responses.
- Raises:
None –
Notes
- Assumes self.gDC, self.gDC2, self.tx_taps, self.rx_taps, and self.dfe_taps
have been set correctly, if the equivalent function parameters have not been provided.
- To generate pulse responses that include all linear EQ except the Rx FFE/DFE
(i.e. - pulse responses suitable for Rx FFE/DFE tap weight optimization, via either optimize.przf() or optimize.mmse()) set rx_taps equal to: [1.0] and dfe_taps equal to: [].
- get_chnls_s32p_wPkg() list[tuple[Network, str]][source]
Augment imported s32p channels, w/ package response.
- get_chnls_s4p_wPkg() list[tuple[Network, str]][source]
Augment imported s4p channels, w/ package response.
- classmethod init(params: dict, chnl_fnames: list[str], vic_id: int, zp_sel: int = 1, num_ui: int = 500, gui: bool = False)[source]
Legacy initializer supports my VITA notebook, which was created before PyChOpMarg was altered to support a GUI.
- loc_curs(pulse_resp: 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.
- 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
- 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.)
- nDFE = 1
- nRxPreTaps = 3
- nRxTaps = 15
- nTxTaps = 6
- norm_mode = 3
- nspui = 32
- opt_eq(do_opt_eq: bool = True, tx_taps: ndarray[Any, dtype[Real]] | None = None, opt_mode: OptMode | None = None, norm_mode: NormMode | None = None, unit_amp: bool | None = None) bool[source]
Find the optimum values for the linear equalization parameters: c[n], gDC, gDC2, and w[n] as per IEEE 802.3-22 93A.1.6 (or, [1] slide 11 if MMSE has been chosen).
- Keyword Arguments:
do_opt_eq – Perform optimization of linear EQ when True. Default: True
tx_taps – Used when do_opt_eq = False. Default: None
opt_mode – Optimization mode. Default: None (i.e. - Use self.opt_mode.)
norm_mode – The tap weight normalization mode to use. Default: None (i.e. - Use self.norm_mode.)
unit_amp – Enforce unit pulse response amplitude when True. (For comparing przf() results to mmse() results.) Default: None (i.e. - Use self.unit_amp.)
- Returns:
True if no errors encountered; False otherwise.
- opt_mode = 2
- pulse_resp(H: ndarray[Any, dtype[Comp]]) ndarray[Any, dtype[Real]][source]
Return the unit pulse response, p(t), corresponding to the given voltage transfer function, H(f), according to (93A-24).
- Parameters:
H – The voltage transfer function, H(f). Note: Possitive frequency components only, including fN.
- Returns:
The pulse response corresponding to the given voltage transfer function.
- Raises:
ValueError – If the length of the given voltage transfer function differs from that of the system frequency vector.
Notes
- It is at this point in the signal processing chain that we change
time domains.
- rx_taps = array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
- rx_taps_max = array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
- rx_taps_min = array([-1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1.])
- sC(c: float) Network[source]
Return the 2-port network corresponding to a shunt capacitance, according to (93A-8).
- Parameters:
c – Value of shunt capacitance (F).
- Returns:
2-port network equivalent to shunt capacitance, calculated at given frequencies.
- Raises:
None –
- property sDieLadder: Network
On-die parasitic capacitance/inductance ladder network.
- property sPkgNEXT: Network
NEXT package response.
- property sPkgRx: Network
Rx package response.
- property sPkgTx: Network
Tx package response.
- property sZp: Network
THRU/FEXT package transmission line.
- property sZpNEXT: Network
NEXT package transmission line.
- set_params(params: dict[str, Any]) None[source]
Set the COM instance parameters, according to the given dictionary.
- Parameters:
params – Dictionary of COM parameter values.
- Raises:
KeyError – If an expected key is not found in the provided dictionary.
ValueError – If certain invariants aren’t met.
- sigma_ISI = 0.0
- sigma_J = 0.0
- sigma_N = 0.0
- sigma_Rj = 0.01
- sigma_Tx = 0.0
- sigma_XT = 0.0
- status_str = 'Ready'
- property t_irfft: ndarray[Any, dtype[Real]]
irfft() result time index (s) (i.e. - time vector coupled to frequency vector).
- tau = 0.006141
- property times: ndarray[Any, dtype[Real]]
System time vector (s); decoupled from system frequency vector!
- tmax = 1e-08
- tr = 1e-11
- property tx_combs: list[list[float]]
All possible Tx tap weight combinations.
- tx_n_post = 3
- tx_taps = array([0., 0., 0., 0., 0., 0.])
- tx_taps_max = array([1., 1., 1., 1., 1., 1.])
- tx_taps_min = array([-1., -1., -1., -1., -1., -1.])
- tx_taps_pos = array([-3, -2, -1, 1, 2, 3])
- tx_taps_step = array([0.25, 0.25, 0.25, 0.25, 0.25, 0.25])
- property ui: float
Unit interval (s).
- unit_amp = False
- vic_chnl_ix = 1
- zc = [87.5, 92.5]
- zp = 12
- zp_B = 1.8
- zp_vals = [12, 33]