PyChOpMarg 2.1.1__tar.gz → 2.1.2__tar.gz
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.
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/PKG-INFO +1 -1
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/pyproject.toml +1 -1
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/PyChOpMarg.egg-info/PKG-INFO +1 -1
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/com.py +75 -61
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/common.py +3 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/noise.py +20 -15
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/optimize.py +44 -32
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/utility/filter.py +10 -16
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/utility/general.py +18 -16
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/utility/probability.py +11 -10
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/utility/sparams.py +25 -16
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/LICENSE +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/README.md +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/setup.cfg +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/PyChOpMarg.egg-info/SOURCES.txt +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/PyChOpMarg.egg-info/dependency_links.txt +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/PyChOpMarg.egg-info/entry_points.txt +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/PyChOpMarg.egg-info/requires.txt +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/PyChOpMarg.egg-info/top_level.txt +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/__init__.py +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/__main__.py +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/cli.py +0 -0
- {pychopmarg-2.1.1 → pychopmarg-2.1.2}/src/pychopmarg/utility/__init__.py +0 -0
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "PyChOpMarg"
|
|
11
11
|
description = "Python implementation of COM, as per IEEE 802.3-22 Annex 93A/178A."
|
|
12
|
-
version = "2.1.
|
|
12
|
+
version = "2.1.2"
|
|
13
13
|
authors = [{name = "David Banas", email = "capn.freako@gmail.com"}]
|
|
14
14
|
urls = { documentation = "https://pychopmarg.readthedocs.io/en/latest/"}
|
|
15
15
|
readme = "README.md"
|
|
@@ -48,7 +48,12 @@ class OptMode(Enum):
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-methods
|
|
51
|
-
"
|
|
51
|
+
"""
|
|
52
|
+
Encoding of the IEEE 802.3-22 Annex 93A/178A 'Channel Operating Margin' (COM) specification.
|
|
53
|
+
|
|
54
|
+
ToDo:
|
|
55
|
+
1. Clean up unused attributes.
|
|
56
|
+
"""
|
|
52
57
|
|
|
53
58
|
status_str = str("Ready")
|
|
54
59
|
debug = bool(False)
|
|
@@ -149,7 +154,6 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
149
154
|
|
|
150
155
|
# - Results
|
|
151
156
|
# -- COM
|
|
152
|
-
# ToDo: Clean up unused attributes.
|
|
153
157
|
com = float(0.0)
|
|
154
158
|
com_As = float(0.0)
|
|
155
159
|
com_cursor_ix = int(0)
|
|
@@ -250,8 +254,8 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
250
254
|
Default: None
|
|
251
255
|
|
|
252
256
|
Notes:
|
|
253
|
-
1. The instance's current value(s) for
|
|
254
|
-
|
|
257
|
+
1. The instance's current value(s) for ``gDC`` and ``gDC2`` are used if not provided.
|
|
258
|
+
(Necessary, to accommodate sweeping when optimizing EQ.)
|
|
255
259
|
"""
|
|
256
260
|
gDC = gDC or self.gDC
|
|
257
261
|
gDC2 = gDC2 or self.gDC2
|
|
@@ -672,9 +676,9 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
672
676
|
|
|
673
677
|
Notes:
|
|
674
678
|
1. It is at this point in the analysis that the "raw" Touchstone data
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
679
|
+
gets interpolated to our system frequency vector.
|
|
680
|
+
|
|
681
|
+
2. After this step, the package and R0/Rd mismatch have been accounted for, but not the EQ.
|
|
678
682
|
"""
|
|
679
683
|
|
|
680
684
|
assert s2p.s[0].shape == (2, 2), ValueError("I can only convert 2-port networks.")
|
|
@@ -704,15 +708,15 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
704
708
|
|
|
705
709
|
Keyword Args:
|
|
706
710
|
tx_taps: Tx FFE tap weights.
|
|
707
|
-
Default: None (i.e. - Use
|
|
711
|
+
Default: None (i.e. - Use ``self.tx_taps``.)
|
|
708
712
|
gDC: CTLE first stage d.c. gain (dB).
|
|
709
|
-
Default: None (i.e. - Use
|
|
713
|
+
Default: None (i.e. - Use ``self.gDC``.)
|
|
710
714
|
gDC2: CTLE second stage d.c. gain (dB).
|
|
711
|
-
Default: None (i.e. - Use
|
|
715
|
+
Default: None (i.e. - Use ``self.gDC2``.)
|
|
712
716
|
rx_taps: Rx FFE tap weights.
|
|
713
|
-
Default: None (i.e. - Use
|
|
717
|
+
Default: None (i.e. - Use ``self.rx_taps``.)
|
|
714
718
|
dfe_taps: Rx DFE tap weights.
|
|
715
|
-
Default: None (i.e. - Use
|
|
719
|
+
Default: None (i.e. - Use ``self.dfe_taps``.)
|
|
716
720
|
passive_RxFFE: Enforce passivity of Rx FFE when True.
|
|
717
721
|
Default: True
|
|
718
722
|
|
|
@@ -724,11 +728,13 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
724
728
|
|
|
725
729
|
Notes:
|
|
726
730
|
1. It is in this processing step that linear EQ is first applied.
|
|
727
|
-
2. Any unprovided EQ values are taken from the `COM` instance.
|
|
728
|
-
If you really want to omit a particular EQ component then call with:
|
|
729
731
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
+
2. Any unprovided EQ values are taken from the ``COM`` instance.
|
|
733
|
+
If you really want to omit a particular EQ component then call with:
|
|
734
|
+
|
|
735
|
+
- ``tx_taps``: []
|
|
736
|
+
- ``rx_taps``: [1.0]
|
|
737
|
+
- ``gDC``/``gDC2``: 0
|
|
732
738
|
"""
|
|
733
739
|
|
|
734
740
|
assert s2p.s[0, :, :].shape == (2, 2), ValueError(
|
|
@@ -777,7 +783,7 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
777
783
|
|
|
778
784
|
Notes:
|
|
779
785
|
1. It is at this point in the signal processing chain that we change
|
|
780
|
-
|
|
786
|
+
time domains.
|
|
781
787
|
"""
|
|
782
788
|
|
|
783
789
|
assert len(H) == len(self.freqs), ValueError(
|
|
@@ -799,17 +805,17 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
799
805
|
|
|
800
806
|
Keyword Args:
|
|
801
807
|
ntwks: The list of networks to generate pulse responses for.
|
|
802
|
-
Default: None (i.e. - Use
|
|
808
|
+
Default: None (i.e. - Use ``self.chnls``.)
|
|
803
809
|
gDC: Rx CTLE first stage d.c. gain.
|
|
804
|
-
Default: None (i.e. - Use
|
|
810
|
+
Default: None (i.e. - Use ``self.gDC``.)
|
|
805
811
|
gDC2: Rx CTLE second stage d.c. gain.
|
|
806
|
-
Default: None (i.e. - Use
|
|
812
|
+
Default: None (i.e. - Use ``self.gDC2``.)
|
|
807
813
|
tx_taps: Desired Tx tap weights.
|
|
808
|
-
Default: None (i.e. - Use
|
|
814
|
+
Default: None (i.e. - Use ``self.tx_taps``.)
|
|
809
815
|
rx_taps: Desired Rx FFE tap weights.
|
|
810
|
-
Default: None (i.e. - Use
|
|
816
|
+
Default: None (i.e. - Use ``self.rx_taps``.)
|
|
811
817
|
dfe_taps: Desired Rx DFE tap weights.
|
|
812
|
-
Default: None (i.e. - Use
|
|
818
|
+
Default: None (i.e. - Use ``self.dfe_taps``.)
|
|
813
819
|
apply_eq: Include linear EQ when True; otherwise, exclude it.
|
|
814
820
|
(Allows for pulse response generation of terminated, but unequalized, channel.)
|
|
815
821
|
Default: True
|
|
@@ -817,16 +823,14 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
817
823
|
Returns:
|
|
818
824
|
list of pulse responses.
|
|
819
825
|
|
|
820
|
-
Raises:
|
|
821
|
-
None
|
|
822
|
-
|
|
823
826
|
Notes:
|
|
824
|
-
1. Assumes
|
|
825
|
-
|
|
827
|
+
1. Assumes ``self.gDC``, ``self.gDC2``, ``self.tx_taps``, ``self.rx_taps``, and ``self.dfe_taps``
|
|
828
|
+
have been set correctly, if the equivalent function parameters have not been provided.
|
|
829
|
+
|
|
826
830
|
2. To generate pulse responses that include all linear EQ except the Rx FFE/DFE
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
831
|
+
(i.e. - pulse responses suitable for Rx FFE/DFE tap weight optimization,
|
|
832
|
+
via either ``optimize.przf()`` or ``optimize.mmse()``),
|
|
833
|
+
set ``rx_taps`` equal to: ``[1.0]`` and ``dfe_taps`` equal to: ``[]``.
|
|
830
834
|
"""
|
|
831
835
|
|
|
832
836
|
gDC = gDC or self.gDC # The more Pythonic way, but doesn't work for lists in newer versions of Python.
|
|
@@ -880,7 +884,7 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
880
884
|
Default: 0.001 (i.e. - 0.1%, as per Note 2 of 93A.1.7.1)
|
|
881
885
|
|
|
882
886
|
Returns:
|
|
883
|
-
The subset of
|
|
887
|
+
The subset of ``pr_samps`` passing filtration.
|
|
884
888
|
"""
|
|
885
889
|
|
|
886
890
|
thresh = As * rel_thresh
|
|
@@ -930,8 +934,8 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
930
934
|
|
|
931
935
|
Notes:
|
|
932
936
|
1. As per v3.70 of the COM MATLAB code, we only minimize the
|
|
933
|
-
|
|
934
|
-
|
|
937
|
+
residual of (93A-25); we don't require solving it exactly.
|
|
938
|
+
(We do, however, give priority to exact solutions.)
|
|
935
939
|
"""
|
|
936
940
|
|
|
937
941
|
M = self.nspui
|
|
@@ -993,20 +997,19 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
993
997
|
norm_mode: The tap weight normalization mode to use.
|
|
994
998
|
Default: None (i.e. - Use ``self.norm_mode``.)
|
|
995
999
|
unit_amp: Enforce unit pulse response amplitude when True.
|
|
996
|
-
(For comparing
|
|
1000
|
+
(For comparing ``optimize.przf()`` results to ``optimize.mmse()`` results.)
|
|
997
1001
|
Default: None (i.e. - Use ``self.unit_amp``.)
|
|
998
1002
|
|
|
999
1003
|
Returns:
|
|
1000
1004
|
The resultant figure of merit.
|
|
1001
1005
|
|
|
1002
|
-
Raises:
|
|
1003
|
-
None
|
|
1004
|
-
|
|
1005
1006
|
Notes:
|
|
1006
1007
|
1. See: IEEE 802.3-2022 93A.1.6.
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1008
|
+
|
|
1009
|
+
2. When not provided, the values for ``gDC`` and ``gDC2`` are taken from the ``COM`` instance.
|
|
1010
|
+
|
|
1011
|
+
3. Unlike other member functions of the ``COM`` class,
|
|
1012
|
+
this function *optimizes* the Rx FFE tap weights when they are not provided.
|
|
1010
1013
|
"""
|
|
1011
1014
|
|
|
1012
1015
|
# Honor any mode overrides.
|
|
@@ -1146,25 +1149,28 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
1146
1149
|
unit_amp: Optional[bool] = None
|
|
1147
1150
|
) -> bool:
|
|
1148
1151
|
"""
|
|
1149
|
-
Find the optimum values for the linear equalization parameters:
|
|
1150
|
-
c[n]
|
|
1152
|
+
Find and set the optimum values for the linear equalization parameters:
|
|
1153
|
+
``c[n]``, ``gDC``, ``gDC2``, and ``w[n]`` as per IEEE 802.3-22 93A.1.6
|
|
1151
1154
|
(or, [1] slide 11 if MMSE has been chosen).
|
|
1152
1155
|
|
|
1153
1156
|
Keyword Args:
|
|
1154
1157
|
do_opt_eq: Perform optimization of linear EQ when True.
|
|
1155
1158
|
Default: True
|
|
1156
|
-
tx_taps: Used when
|
|
1159
|
+
tx_taps: Used when ``do_opt_eq`` = False.
|
|
1157
1160
|
Default: None
|
|
1158
1161
|
opt_mode: Optimization mode.
|
|
1159
|
-
Default: None (i.e. - Use
|
|
1162
|
+
Default: None (i.e. - Use ``self.opt_mode``.)
|
|
1160
1163
|
norm_mode: The tap weight normalization mode to use.
|
|
1161
|
-
Default: None (i.e. - Use
|
|
1164
|
+
Default: None (i.e. - Use ``self.norm_mode``.)
|
|
1162
1165
|
unit_amp: Enforce unit pulse response amplitude when True.
|
|
1163
|
-
(For comparing
|
|
1164
|
-
Default: None (i.e. - Use
|
|
1166
|
+
(For comparing ``przf()`` results to ``mmse()`` results.)
|
|
1167
|
+
Default: None (i.e. - Use ``self.unit_amp``.)
|
|
1165
1168
|
|
|
1166
1169
|
Returns:
|
|
1167
1170
|
True if no errors encountered; False otherwise.
|
|
1171
|
+
|
|
1172
|
+
Notes:
|
|
1173
|
+
1. The found optimum equalization values are set for the instance.
|
|
1168
1174
|
"""
|
|
1169
1175
|
|
|
1170
1176
|
if do_opt_eq:
|
|
@@ -1267,29 +1273,37 @@ class COM(): # pylint: disable=too-many-instance-attributes,too-many-public-met
|
|
|
1267
1273
|
(In support of MMSE.)
|
|
1268
1274
|
Default: None
|
|
1269
1275
|
opt_mode: Optimization mode.
|
|
1270
|
-
Default: None (i.e. - Use
|
|
1276
|
+
Default: None (i.e. - Use ``self.opt_mode``.)
|
|
1271
1277
|
norm_mode: The tap weight normalization mode to use.
|
|
1272
|
-
Default: None (i.e. - Use
|
|
1278
|
+
Default: None (i.e. - Use ``self.norm_mode``.)
|
|
1273
1279
|
unit_amp: Enforce unit pulse response amplitude when True.
|
|
1274
|
-
(For comparing
|
|
1275
|
-
Default: None (i.e. - Use
|
|
1280
|
+
(For comparing ``przf()`` results to ``mmse()`` results.)
|
|
1281
|
+
Default: None (i.e. - Use ``self.unit_amp``.)
|
|
1276
1282
|
dbg_dict: Optional dictionary into which debugging values may be stashed,
|
|
1277
1283
|
for later analysis.
|
|
1278
1284
|
Default: None
|
|
1279
1285
|
|
|
1280
1286
|
Returns:
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1287
|
+
A triplet containing
|
|
1288
|
+
|
|
1289
|
+
- signal amplitude (V)
|
|
1290
|
+
- noise + interference amplitude (V)
|
|
1291
|
+
- cursor location within victim pulse response vector
|
|
1284
1292
|
|
|
1285
1293
|
Notes:
|
|
1286
1294
|
1. Assumes the following instance variables have been set optimally:
|
|
1287
|
-
|
|
1288
|
-
-
|
|
1289
|
-
-
|
|
1290
|
-
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1295
|
+
|
|
1296
|
+
- ``gDC``
|
|
1297
|
+
- ``gDC2``
|
|
1298
|
+
- ``tx_taps``
|
|
1299
|
+
- ``rx_taps``
|
|
1300
|
+
|
|
1301
|
+
(This assumption is embedded into the ``gen_pulse_resps()`` function.)
|
|
1302
|
+
|
|
1303
|
+
2. Fills in the ``com_results`` dictionary w/ various useful values for debugging.
|
|
1304
|
+
|
|
1305
|
+
ToDo:
|
|
1306
|
+
1. ``DER0 / 2`` in ``Ani`` calculation?
|
|
1293
1307
|
"""
|
|
1294
1308
|
|
|
1295
1309
|
# Honor any mode overrides.
|
|
@@ -6,6 +6,9 @@ Original author: David Banas <capn.freako@gmail.com>
|
|
|
6
6
|
Original date: March 3, 2024 (Copied from `pybert.utility`.)
|
|
7
7
|
|
|
8
8
|
Copyright (c) 2024 David Banas; all rights reserved World wide.
|
|
9
|
+
|
|
10
|
+
ToDo:
|
|
11
|
+
1. Specify ``COMParams`` concretely.
|
|
9
12
|
"""
|
|
10
13
|
|
|
11
14
|
from typing import TypeVar, TypeAlias, Any
|
|
@@ -147,25 +147,28 @@ class NoiseCalc(): # pylint: disable=too-many-instance-attributes
|
|
|
147
147
|
|
|
148
148
|
def from_irfft(self, x: Rvec) -> Rvec:
|
|
149
149
|
"""
|
|
150
|
-
Interpolate
|
|
150
|
+
Interpolate ``irfft()`` output to ``t`` and subsample at fBaud.
|
|
151
151
|
|
|
152
152
|
Args:
|
|
153
|
-
x:
|
|
153
|
+
x: ``irfft()`` results to be interpolated and subsampled.
|
|
154
154
|
|
|
155
155
|
Returns:
|
|
156
|
-
|
|
156
|
+
Interpolated and subsampled vector.
|
|
157
157
|
|
|
158
158
|
Raises:
|
|
159
|
-
IndexError: If length of input doesn't match length of
|
|
159
|
+
IndexError: If length of input doesn't match length of ``t_irfft`` vector.
|
|
160
160
|
|
|
161
161
|
Notes:
|
|
162
|
-
1. Input vector is shifted, such that its peak occurs at
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
162
|
+
1. Input vector is shifted, such that its peak occurs at ``0.1 * max(t)``, before interpolating.
|
|
163
|
+
This is done to:
|
|
164
|
+
|
|
165
|
+
* ensure that we don't omit any non-causal behavior,
|
|
166
|
+
which ends up at the end of an IFFT output vector
|
|
167
|
+
when the peak is very near the beginning, and
|
|
168
|
+
|
|
169
|
+
* to ensure that the majority of our available time span
|
|
170
|
+
is available for capturing reflections.
|
|
171
|
+
|
|
169
172
|
2. The sub-sampling phase is adjusted, so as to ensure that we catch the peak.
|
|
170
173
|
"""
|
|
171
174
|
|
|
@@ -193,8 +196,8 @@ class NoiseCalc(): # pylint: disable=too-many-instance-attributes
|
|
|
193
196
|
uniformly sampled over [0, PI] (rads./s norm.).
|
|
194
197
|
|
|
195
198
|
Notes:
|
|
196
|
-
1. Re: the scaling term:
|
|
197
|
-
|
|
199
|
+
1. Re: the scaling term: ``2 * self.f[-1]``, when combined w/
|
|
200
|
+
the implicit ``1/N`` of the ``irfft()`` function, this gives ``df``.
|
|
198
201
|
"""
|
|
199
202
|
# "/ 2" in [1] omitted, since we're only considering: m >= 0.
|
|
200
203
|
rslt = self.eta0 * 1e-9 * abs(self.Hr * self.Hctf) ** 2
|
|
@@ -209,8 +212,7 @@ class NoiseCalc(): # pylint: disable=too-many-instance-attributes
|
|
|
209
212
|
agg_pulse_resp: Aggressor pulse response (V).
|
|
210
213
|
|
|
211
214
|
Returns:
|
|
212
|
-
|
|
213
|
-
uniformly sampled over [0, PI] (rads./s norm.).
|
|
215
|
+
One-sided crosstalk PSD at Rx FFE input, uniformly sampled over [0, PI] (rads./s norm.).
|
|
214
216
|
"""
|
|
215
217
|
|
|
216
218
|
nspui = self.nspui
|
|
@@ -224,6 +226,9 @@ class NoiseCalc(): # pylint: disable=too-many-instance-attributes
|
|
|
224
226
|
"""
|
|
225
227
|
One-sided Tx noise PSD at Rx FFE input,
|
|
226
228
|
uniformly sampled over [0, PI] (rads./s norm.).
|
|
229
|
+
|
|
230
|
+
ToDo:
|
|
231
|
+
1. Do I need to honor ``ts_ix``?
|
|
227
232
|
"""
|
|
228
233
|
|
|
229
234
|
Tb = self.Tb
|
|
@@ -25,10 +25,18 @@ from pychopmarg.noise import NoiseCalc
|
|
|
25
25
|
|
|
26
26
|
class NormMode(Enum):
|
|
27
27
|
"Tap weight normalization mode."
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
|
|
29
|
+
P8023dj = 1
|
|
30
|
+
"As per standard (i.e. - clip then renormalize for unit amplitude pulse response.)"
|
|
31
|
+
|
|
32
|
+
Scaled = 2
|
|
33
|
+
"Uniformly and minimally scaled to bring tap weights just within their limits."
|
|
34
|
+
|
|
35
|
+
Unaltered = 3
|
|
36
|
+
"Use constrained optimization solution, unchanged."
|
|
37
|
+
|
|
38
|
+
UnitDcGain = 4
|
|
39
|
+
"Tap weights are uniformly scaled, to yield unity gain at d.c."
|
|
32
40
|
|
|
33
41
|
|
|
34
42
|
def scale_taps(w: Rvec, w_min: Optional[Rvec] = None, w_max: Optional[Rvec] = None) -> Rvec:
|
|
@@ -40,12 +48,12 @@ def scale_taps(w: Rvec, w_min: Optional[Rvec] = None, w_max: Optional[Rvec] = No
|
|
|
40
48
|
|
|
41
49
|
Keyword Args:
|
|
42
50
|
w_min: Minimum tap weights.
|
|
43
|
-
Default: None (Use
|
|
51
|
+
Default: None (Use ``-ones(len(w))``.)
|
|
44
52
|
w_max: Maximum tap weights.
|
|
45
|
-
Default: None (Use
|
|
53
|
+
Default: None (Use ``ones(len(w))``.)
|
|
46
54
|
|
|
47
55
|
Returns:
|
|
48
|
-
|
|
56
|
+
Tap weights, scaled proportionally to just fit inside min/max limits.
|
|
49
57
|
"""
|
|
50
58
|
|
|
51
59
|
if w_min is None:
|
|
@@ -82,18 +90,18 @@ def clip_taps(
|
|
|
82
90
|
|
|
83
91
|
Args:
|
|
84
92
|
w: The tap weights to clip.
|
|
85
|
-
curs_ix: The index, in
|
|
93
|
+
curs_ix: The index, in ``w``, of the cursor tap.
|
|
86
94
|
|
|
87
95
|
Keyword Args:
|
|
88
96
|
w_min: Minimum tap weights.
|
|
89
|
-
Default: None (Use
|
|
97
|
+
Default: None (Use ``-ones(len(w))``.)
|
|
90
98
|
w_max: Maximum tap weights.
|
|
91
|
-
Default: None (Use
|
|
99
|
+
Default: None (Use ``ones(len(w))``.)
|
|
92
100
|
obey_spec: Allow cursor tap weight to grow w/o bound, as per D1.2, when True.
|
|
93
101
|
Default: True
|
|
94
102
|
|
|
95
103
|
Returns:
|
|
96
|
-
|
|
104
|
+
Tap weights, clipped accordingly.
|
|
97
105
|
"""
|
|
98
106
|
|
|
99
107
|
if w_min is None:
|
|
@@ -136,7 +144,7 @@ def przf( # pylint: disable=too-many-arguments,too-many-positional-arguments,to
|
|
|
136
144
|
norm_mode: NormMode = NormMode.P8023dj, unit_amp: bool = False
|
|
137
145
|
) -> tuple[Rvec, Rvec, Rvec]:
|
|
138
146
|
"""
|
|
139
|
-
Optimize FFE tap weights, via
|
|
147
|
+
Optimize FFE tap weights, via *Pulse Response Zero Forcing* (PRZF).
|
|
140
148
|
|
|
141
149
|
Args:
|
|
142
150
|
pulse_resp: The pulse response to be filtered.
|
|
@@ -151,20 +159,22 @@ def przf( # pylint: disable=too-many-arguments,too-many-positional-arguments,to
|
|
|
151
159
|
|
|
152
160
|
Keyword Args:
|
|
153
161
|
norm_mode: The tap weight normalization mode to use.
|
|
154
|
-
Default:
|
|
162
|
+
Default: ``P8023dj``
|
|
155
163
|
unit_amp: Enforce unit pulse response amplitude when True.
|
|
156
|
-
(For comparing results to
|
|
164
|
+
(For comparing results to ``mmse()``.)
|
|
157
165
|
Default: False
|
|
158
166
|
|
|
159
167
|
Returns:
|
|
160
|
-
A triple consisting of
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
168
|
+
A triple consisting of
|
|
169
|
+
|
|
170
|
+
- The optimum FFE tap weights.
|
|
171
|
+
- The optimum DFE tap weights.
|
|
172
|
+
- The pulse response samples used in optimization.
|
|
164
173
|
|
|
165
174
|
Notes:
|
|
166
175
|
1. The algorithm implemented below is a slightly modified version of:
|
|
167
|
-
|
|
176
|
+
|
|
177
|
+
Mellitz, R., Lusted, K., *RX FFE Implementation Algorithm for COM 4.1*,
|
|
168
178
|
IEEE P802.3dj Task Force, August 31, 2023.
|
|
169
179
|
|
|
170
180
|
ToDo:
|
|
@@ -241,7 +251,7 @@ def mmse( # pylint: disable=too-many-arguments,too-many-positional-arguments,to
|
|
|
241
251
|
ts_sweep: float = 0.5, norm_mode: NormMode = NormMode.P8023dj
|
|
242
252
|
) -> dict[str, Any]:
|
|
243
253
|
"""
|
|
244
|
-
Optimize Rx FFE tap weights, via
|
|
254
|
+
Optimize Rx FFE tap weights, via *Minimum Mean Squared Error* (MMSE).
|
|
245
255
|
|
|
246
256
|
Args:
|
|
247
257
|
theNoiseCalc: Initialized instance of ``NoiseCalc`` class.
|
|
@@ -257,25 +267,27 @@ def mmse( # pylint: disable=too-many-arguments,too-many-positional-arguments,to
|
|
|
257
267
|
|
|
258
268
|
Keyword Args:
|
|
259
269
|
ts_sweep: The cursor sampling time "search radius" around the peak pulse response amplitude (UI).
|
|
260
|
-
Default: 0.5 (i.e. -
|
|
270
|
+
Default: 0.5 (i.e. - ``ts`` within [-UI/2, +UI/2] of peak location)
|
|
261
271
|
norm_mode: The tap weight normalization mode to use.
|
|
262
|
-
Default:
|
|
272
|
+
Default: ``P8023dj``
|
|
263
273
|
|
|
264
274
|
Returns:
|
|
265
|
-
A dictionary containing
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
275
|
+
A dictionary containing
|
|
276
|
+
|
|
277
|
+
* the optimized FFE tap weights, in the "rx_taps" key,
|
|
278
|
+
* the optimized DFE tap weights, in the "dfe_tap_weights" key, and
|
|
279
|
+
* several other values of general utility for plotting/analysis/debugging.
|
|
269
280
|
|
|
270
281
|
Raises:
|
|
271
|
-
ValueError
|
|
272
|
-
|
|
273
|
-
- there is insufficient room at the beginning/end of the pulse response vector, for `ts` sweeping.
|
|
282
|
+
ValueError: If ``dw`` > ``Nw``, or there is insufficient room at the beginning/end \
|
|
283
|
+
of the pulse response vector for ``ts`` sweeping.
|
|
274
284
|
|
|
275
285
|
Notes:
|
|
276
|
-
1. The optimization technique encoded here is taken from the following references
|
|
277
|
-
|
|
278
|
-
|
|
286
|
+
1. The optimization technique encoded here is taken from the following references
|
|
287
|
+
|
|
288
|
+
[1] Healey, A., Hegde, R., *Reference receiver framework for 200G/lane electrical interfaces and PHYs*,
|
|
289
|
+
IEEE P802.3dj Task Force, Jan. 2024
|
|
290
|
+
|
|
279
291
|
[2] D1.2 of P802.3dj, IEEE P802.3dj Task Force, Aug. 2024
|
|
280
292
|
"""
|
|
281
293
|
|
|
@@ -3,7 +3,7 @@ Filtering utilities for PyChOpMarg.
|
|
|
3
3
|
|
|
4
4
|
Original author: David Banas <capn.freako@gmail.com>
|
|
5
5
|
|
|
6
|
-
Original date: March 3, 2024
|
|
6
|
+
Original date: March 3, 2024
|
|
7
7
|
|
|
8
8
|
Copyright (c) 2024 David Banas; all rights reserved World wide.
|
|
9
9
|
"""
|
|
@@ -26,19 +26,16 @@ def calc_Hctle( # pylint: disable=too-many-arguments,too-many-positional-argume
|
|
|
26
26
|
according to (93A-22).
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
|
-
f: Frequencies at which to calculate
|
|
29
|
+
f: Frequencies at which to calculate ``Hctle`` (Hz).
|
|
30
30
|
fz: First stage zero frequency (Hz).
|
|
31
31
|
fp1: First stage lower pole frequency (Hz).
|
|
32
32
|
fp2: First stage upper pole frequency (Hz).
|
|
33
33
|
fLF: Second stage pole/zero frequency (Hz).
|
|
34
|
-
gDC:
|
|
35
|
-
gDC2:
|
|
34
|
+
gDC: First stage d.c. gain (dB).
|
|
35
|
+
gDC2: Second stage d.c. gain (dB).
|
|
36
36
|
|
|
37
37
|
Returns:
|
|
38
38
|
The complex voltage transfer function, H(f), for the CTLE.
|
|
39
|
-
|
|
40
|
-
Raises:
|
|
41
|
-
None
|
|
42
39
|
"""
|
|
43
40
|
g1 = from_dB(gDC)
|
|
44
41
|
g2 = from_dB(gDC2)
|
|
@@ -56,20 +53,17 @@ def calc_Hffe(
|
|
|
56
53
|
Calculate the voltage transfer function, H(f), for a digital FFE, according to (93A-21).
|
|
57
54
|
|
|
58
55
|
Args:
|
|
59
|
-
freqs: Frequencies at which to calculate
|
|
56
|
+
freqs: Frequencies at which to calculate ``Hffe`` (Hz).
|
|
60
57
|
td: Tap delay time (s).
|
|
61
58
|
tap_weights: The filter tap weights.
|
|
62
59
|
n_post: The number of post-cursor taps.
|
|
63
60
|
|
|
64
61
|
Keyword Args:
|
|
65
|
-
hasCurs:
|
|
62
|
+
hasCurs: ``tap_weights`` includes the cursor tap weight when True.
|
|
66
63
|
Default: False (Cursor tap weight will be calculated.)
|
|
67
64
|
|
|
68
65
|
Returns:
|
|
69
66
|
The complex voltage transfer function, H(f), for the FFE.
|
|
70
|
-
|
|
71
|
-
Raises:
|
|
72
|
-
None
|
|
73
67
|
"""
|
|
74
68
|
|
|
75
69
|
bs = list(np.array(tap_weights).flatten())
|
|
@@ -82,10 +76,10 @@ def calc_Hffe(
|
|
|
82
76
|
|
|
83
77
|
def calc_Hdfe(freqs: Rvec, td: float, tap_weights: Rvec) -> Cvec:
|
|
84
78
|
"""
|
|
85
|
-
Calculate the voltage transfer function, H(f), for a
|
|
79
|
+
Calculate the voltage transfer function, H(f), for a *Decision Feedback Equalizer* (DFE).
|
|
86
80
|
|
|
87
81
|
Args:
|
|
88
|
-
freqs: Frequencies at which to calculate
|
|
82
|
+
freqs: Frequencies at which to calculate ``Hdfe`` (Hz).
|
|
89
83
|
td: Tap delay time (s).
|
|
90
84
|
tap_weights: The vector of filter tap weights.
|
|
91
85
|
|
|
@@ -100,7 +94,7 @@ def calc_Hdfe(freqs: Rvec, td: float, tap_weights: Rvec) -> Cvec:
|
|
|
100
94
|
|
|
101
95
|
def null_filter(nTaps: int, nPreTaps: int = 0) -> Rvec:
|
|
102
96
|
"""
|
|
103
|
-
Construct a null filter w/
|
|
97
|
+
Construct a null filter w/ ``nTaps`` taps and (optionally) ``nPreTaps`` pre-cursor taps.
|
|
104
98
|
|
|
105
99
|
Args:
|
|
106
100
|
nTaps: Total number of taps, including the cursor tap.
|
|
@@ -110,7 +104,7 @@ def null_filter(nTaps: int, nPreTaps: int = 0) -> Rvec:
|
|
|
110
104
|
Default: 0
|
|
111
105
|
|
|
112
106
|
Returns:
|
|
113
|
-
|
|
107
|
+
The filter tap weight vector, including the cursor tap weight.
|
|
114
108
|
"""
|
|
115
109
|
|
|
116
110
|
assert nTaps > 0, ValueError(
|
|
@@ -3,7 +3,7 @@ General purpose utilities for PyChOpMarg.
|
|
|
3
3
|
|
|
4
4
|
Original author: David Banas <capn.freako@gmail.com>
|
|
5
5
|
|
|
6
|
-
Original date: March 3, 2024
|
|
6
|
+
Original date: March 3, 2024
|
|
7
7
|
|
|
8
8
|
Copyright (c) 2024 David Banas; all rights reserved World wide.
|
|
9
9
|
"""
|
|
@@ -43,7 +43,7 @@ def mk_combs(trips: list[tuple[float, float, float]]) -> list[list[float]]:
|
|
|
43
43
|
trips: A list of "(min, max, step)" triples, one per weight.
|
|
44
44
|
|
|
45
45
|
Returns:
|
|
46
|
-
|
|
46
|
+
A list of lists of tap weights, including all possible combinations.
|
|
47
47
|
"""
|
|
48
48
|
ranges = []
|
|
49
49
|
for trip in trips:
|
|
@@ -56,28 +56,30 @@ def mk_combs(trips: list[tuple[float, float, float]]) -> list[list[float]]:
|
|
|
56
56
|
|
|
57
57
|
def from_irfft(x: Rvec, t_irfft: Rvec, t: Rvec, nspui: int) -> Rvec:
|
|
58
58
|
"""
|
|
59
|
-
Interpolate
|
|
59
|
+
Interpolate ``irfft()`` output to ``t`` and subsample at fBaud.
|
|
60
60
|
|
|
61
61
|
Args:
|
|
62
|
-
x:
|
|
63
|
-
t_irfft: Time index vector for
|
|
64
|
-
t: Desired new time index vector (same units as
|
|
65
|
-
nspui: Number of samples per unit interval
|
|
62
|
+
x: ``irfft()`` results to be interpolated and subsampled.
|
|
63
|
+
t_irfft: Time index vector for ``x``.
|
|
64
|
+
t: Desired new time index vector (same units as ``t_irfft``).
|
|
65
|
+
nspui: Number of samples per unit interval in ``t``.
|
|
66
66
|
|
|
67
67
|
Returns:
|
|
68
|
-
|
|
68
|
+
Interpolated and subsampled vector.
|
|
69
69
|
|
|
70
70
|
Raises:
|
|
71
|
-
IndexError: If length of input doesn't match length of
|
|
71
|
+
IndexError: If length of input doesn't match length of ``t_irfft`` vector.
|
|
72
72
|
|
|
73
73
|
Notes:
|
|
74
|
-
1. Input vector is shifted, such that its peak occurs at
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
1. Input vector is shifted, such that its peak occurs at ``0.1 * max(t)``, before interpolating.
|
|
75
|
+
This is done to:
|
|
76
|
+
|
|
77
|
+
- ensure that we don't omit any non-causal behavior,
|
|
78
|
+
which ends up at the end of an IFFT output vector
|
|
79
|
+
when the peak is very near the beginning, and
|
|
80
|
+
- to ensure that the majority of our available time span
|
|
81
|
+
is available for capturing reflections.
|
|
82
|
+
|
|
81
83
|
2. The sub-sampling phase is adjusted, so as to ensure that we catch the peak.
|
|
82
84
|
"""
|
|
83
85
|
|
|
@@ -3,7 +3,7 @@ Statistical utilities for PyChOpMarg.
|
|
|
3
3
|
|
|
4
4
|
Original author: David Banas <capn.freako@gmail.com>
|
|
5
5
|
|
|
6
|
-
Original date: March 3, 2024
|
|
6
|
+
Original date: March 3, 2024
|
|
7
7
|
|
|
8
8
|
Copyright (c) 2024 David Banas; all rights reserved World wide.
|
|
9
9
|
"""
|
|
@@ -28,7 +28,7 @@ def filt_pr_samps(pr_samps: Rvec, As: float, rel_thresh: float = 0.001) -> Rvec:
|
|
|
28
28
|
Default: 0.001 (i.e. - 0.1%, as per Note 2 of 93A.1.7.1)
|
|
29
29
|
|
|
30
30
|
Returns:
|
|
31
|
-
The subset of
|
|
31
|
+
The subset of ``pr_samps`` passing filtration.
|
|
32
32
|
"""
|
|
33
33
|
thresh = As * rel_thresh
|
|
34
34
|
return np.array(list(filter(lambda x: abs(x) >= thresh, pr_samps)))
|
|
@@ -58,19 +58,20 @@ def delta_pmf( # pylint: disable=too-many-arguments,too-many-positional-argumen
|
|
|
58
58
|
Default: None
|
|
59
59
|
|
|
60
60
|
Returns:
|
|
61
|
-
A pair consisting of
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
A pair consisting of
|
|
62
|
+
|
|
63
|
+
- the voltages corresponding to the bins, and
|
|
64
|
+
- their probabilities.
|
|
64
65
|
|
|
65
66
|
Raises:
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
ValueError: If the given pulse response contains any NaNs.
|
|
68
|
+
ValueError: If a needed shift exceeds half the result vector length.
|
|
68
69
|
|
|
69
70
|
Notes:
|
|
70
71
|
1. The input set of pulse response samples is filtered,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
as per Note 2 of 93A.1.7.1, unless a y-values override
|
|
73
|
+
vector is provided, in which case it is assumed that
|
|
74
|
+
the caller has already done the filtering.
|
|
74
75
|
"""
|
|
75
76
|
|
|
76
77
|
assert not any(np.isnan(h_samps)), ValueError(
|
|
@@ -3,7 +3,7 @@ S-parameter utilities for PyChOpMarg.
|
|
|
3
3
|
|
|
4
4
|
Original author: David Banas <capn.freako@gmail.com>
|
|
5
5
|
|
|
6
|
-
Original date: March 3, 2024
|
|
6
|
+
Original date: March 3, 2024
|
|
7
7
|
|
|
8
8
|
Copyright (c) 2024 David Banas; all rights reserved World wide.
|
|
9
9
|
"""
|
|
@@ -27,7 +27,7 @@ def sdd_21(ntwk: rf.Network, norm: float = 0.5, renumber: bool = False) -> rf.Ne
|
|
|
27
27
|
|
|
28
28
|
Keyword Args:
|
|
29
29
|
norm: Normalization factor. (Default = 0.5)
|
|
30
|
-
renumber: Automatically detect correct through path when True.
|
|
30
|
+
renumber: Automatically detect and correct through path when True.
|
|
31
31
|
Default: False
|
|
32
32
|
|
|
33
33
|
Returns:
|
|
@@ -43,22 +43,27 @@ def sdd_21(ntwk: rf.Network, norm: float = 0.5, renumber: bool = False) -> rf.Ne
|
|
|
43
43
|
|
|
44
44
|
def se2mm(ntwk: rf.Network, norm: float = 0.5, renumber: bool = False) -> rf.Network:
|
|
45
45
|
"""
|
|
46
|
-
Given a 4-port single-ended network,
|
|
46
|
+
Given a 4-port single-ended network,
|
|
47
|
+
return its mixed mode equivalent in the following format:
|
|
48
|
+
|
|
49
|
+
.. math::
|
|
50
|
+
\\begin{bmatrix}
|
|
51
|
+
Sdd11 & Sdd12 & Sdc11 & Sdc12 \\\\
|
|
52
|
+
Sdd21 & Sdd22 & Sdc21 & Sdc22 \\\\
|
|
53
|
+
Scd11 & Scd12 & Scc11 & Scc12 \\\\
|
|
54
|
+
Scd21 & Scd22 & Scc21 & Scc22
|
|
55
|
+
\\end{bmatrix}
|
|
47
56
|
|
|
48
57
|
Args:
|
|
49
58
|
ntwk: 4-port single ended network.
|
|
50
59
|
|
|
51
60
|
Keyword Args:
|
|
52
61
|
norm: Normalization factor. (Default = 0.5)
|
|
53
|
-
renumber: Automatically detect correct through path when True.
|
|
62
|
+
renumber: Automatically detect and correct through path when True.
|
|
54
63
|
Default: False
|
|
55
64
|
|
|
56
65
|
Returns:
|
|
57
|
-
Mixed mode equivalent network
|
|
58
|
-
Sdd11 Sdd12 Sdc11 Sdc12
|
|
59
|
-
Sdd21 Sdd22 Sdc21 Sdc22
|
|
60
|
-
Scd11 Scd12 Scc11 Scc12
|
|
61
|
-
Scd21 Scd22 Scc21 Scc22
|
|
66
|
+
Mixed mode equivalent network.
|
|
62
67
|
|
|
63
68
|
Notes:
|
|
64
69
|
1. A "1->2/3->4" port ordering convention is assumed when `renumber` is False.
|
|
@@ -121,9 +126,10 @@ def import_s32p( # pylint: disable=too-many-locals
|
|
|
121
126
|
|
|
122
127
|
Returns:
|
|
123
128
|
List of 8 pairs, each consisting of:
|
|
129
|
+
|
|
124
130
|
- a 2-port network representing a *differential* channel, and
|
|
125
131
|
- the type of that channel, one of: 'THRU', 'NEXT', or 'FEXT.
|
|
126
|
-
|
|
132
|
+
(First element is the victim and the only one of type 'THRU'.)
|
|
127
133
|
|
|
128
134
|
Raises:
|
|
129
135
|
ValueError: If Touchstone file is not 32-port.
|
|
@@ -132,7 +138,7 @@ def import_s32p( # pylint: disable=too-many-locals
|
|
|
132
138
|
1. Input Touchstone file is assumed single-ended.
|
|
133
139
|
2. The differential through and xtalk channels are returned.
|
|
134
140
|
3. Port 2 of all returned channels correspond to the same physical circuit node,
|
|
135
|
-
|
|
141
|
+
typically, the Rx input node.
|
|
136
142
|
"""
|
|
137
143
|
|
|
138
144
|
# Import and sanity check the Touchstone file.
|
|
@@ -197,8 +203,8 @@ def sCshunt(freqs: Rvec, c: float, r0: float = 50.0) -> rf.Network:
|
|
|
197
203
|
Default: 50 Ohms.
|
|
198
204
|
|
|
199
205
|
Returns:
|
|
200
|
-
|
|
201
|
-
|
|
206
|
+
The network corresponding to a shunt capacitance, ``c``,
|
|
207
|
+
calculated at the given frequencies, ``freqs``.
|
|
202
208
|
"""
|
|
203
209
|
w = TWOPI * np.array(freqs)
|
|
204
210
|
s = 1j * w
|
|
@@ -221,8 +227,8 @@ def sLseries(freqs: Rvec, inductance: float, r0: float = 50.0) -> rf.Network:
|
|
|
221
227
|
Default: 50 Ohms.
|
|
222
228
|
|
|
223
229
|
Returns:
|
|
224
|
-
|
|
225
|
-
|
|
230
|
+
The network corresponding to a series inductance, ``inductance``,
|
|
231
|
+
calculated at the given frequencies, ``freqs``.
|
|
226
232
|
"""
|
|
227
233
|
w = TWOPI * np.array(freqs)
|
|
228
234
|
s = 1j * w
|
|
@@ -242,12 +248,13 @@ def sDieLadderSegment(freqs: Rvec, trip: tuple[float, float, float]) -> rf.Netwo
|
|
|
242
248
|
Args:
|
|
243
249
|
f: List of frequencies to use for network creation (Hz).
|
|
244
250
|
trip: Triple containing:
|
|
251
|
+
|
|
245
252
|
- R0: Reference impedance for network (Ohms).
|
|
246
253
|
- Cd: Shunt capacitance (F).
|
|
247
254
|
- Ls: Series inductance (H).
|
|
248
255
|
|
|
249
256
|
Returns:
|
|
250
|
-
|
|
257
|
+
Two port network for segment.
|
|
251
258
|
"""
|
|
252
259
|
R0, Cd, Ls = trip
|
|
253
260
|
return sCshunt(freqs, Cd, r0=R0) ** sLseries(freqs, Ls, r0=R0)
|
|
@@ -269,6 +276,7 @@ def sPkgTline( # pylint: disable=too-many-arguments,too-many-positional-argumen
|
|
|
269
276
|
tau: Propagation delay (ns/mm).
|
|
270
277
|
gamma0: Propagation loss constant (1/mm).
|
|
271
278
|
z_pairs: List of pairs defining the T-line segments, each containing:
|
|
279
|
+
|
|
272
280
|
- zc: Characteristic impedance of segment (Ohms).
|
|
273
281
|
- zp: Length of segment (mm).
|
|
274
282
|
|
|
@@ -297,6 +305,7 @@ def sPkgTline( # pylint: disable=too-many-arguments,too-many-positional-argumen
|
|
|
297
305
|
|
|
298
306
|
Args:
|
|
299
307
|
z_pair: Pair consisting of:
|
|
308
|
+
|
|
300
309
|
- zc: Characteristic impedance of leg (Ohms).
|
|
301
310
|
- zp: Length of leg (mm).
|
|
302
311
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|