def __init__(self, f, offsetDelay=0.0, offsetZ0=50.0, offsetLoss=0.0, terminationZ0=50.0): """Constructor @param f list of frequencies @param offsetDelay (optional) float electrical length of offset in s (defaults to 0 s) @param offsetZ0 (optional) float real characteristic impedance of offset (defaults to 50 ohms) @param offsetLoss (optional) float loss due to skin-effect defined in Gohms/s at 1 GHz (defaults to 0). @param terminationZ0 (optional) float real impedance of termination. The result is that the class becomes the base-class SParameters with the s-parameters of a load standard. """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sspn = SystemSParametersNumeric(SystemDescriptionParser().AddLines([ 'device offset 2', 'device R 1', 'port 1 offset 1', 'connect offset 2 R 1' ]).SystemDescription()) offsetSParameters = Offset(f, offsetDelay, offsetZ0, offsetLoss) terminationSParameters = TerminationZ(terminationZ0) sp = [] for n in range(len(f)): sspn.AssignSParameters('offset', offsetSParameters[n]) sspn.AssignSParameters('R', terminationSParameters) sp.append(sspn.SParameters()) SParameters.__init__(self, f, sp)
def __init__(self,f,Rp,Rsep,Lp,Gp,Cp,dfp,Rn,Rsen,Ln,Gn,Cn,dfn,Z0=50.,K=0): """Constructor ports are 1,2,3,4 is +1,-1, +2, -2 @param f list of float frequencies @param Rp float DC resistance of positive leg (ohms) @param Rsep float skin-effect resistance of positive leg (ohms/sqrt(Hz)) @param Lp float inductance of positive leg (H) @param Gp float DC conductance of positive leg to ground (S) @param Cp float capacitance of positive leg to ground (F) @param dfp float dissipation factor (loss-tangent) of capacitance of positive leg to ground @param Rn float DC resistance of negative leg (ohms) @param Rsen float skin-effect resistance of negative leg (ohms/sqrt(Hz)) @param Ln float inductance of negative leg (H) @param Gn float DC conductance of negative leg to ground (S) @param Cn float capacitance of negative leg to ground (F) @param dfn float dissipation factor (loss-tangent) of capacitance of negative leg to ground @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to 0). If 0 is specified, then an analytic solution is provided otherwise an approximate solution is provided with all parametric values divided into the integer number of sections. """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.SParameters.Devices.TLineTwoPortRLGC import TLineTwoPortRLGC # pragma: include sdp=SystemDescriptionParser() sdp.AddLines(['device TP 2','device TN 2', 'port 1 TP 1 2 TN 1 3 TP 2 4 TN 2']) self.m_sspn=SystemSParametersNumeric(sdp.SystemDescription()) self.m_spdl=[('TP',TLineTwoPortRLGC(f,Rp,Rsep,Lp,Gp,Cp,dfp,Z0,K)), ('TN',TLineTwoPortRLGC(f,Rn,Rsen,Ln,Gn,Cn,dfn,Z0,K))] SParameters.__init__(self,f,None,Z0)
def __init__(self, f, R, Rse, L, G, C, df, Cm, dfm, Gm, Lm, Z0=50., K=0, scale=1.): """Constructor ports are 1,2,3,4 is +1,-1, +2, -2 @param f list of float frequencies @param R float DC resistance of both legs (ohms) @param Rse float skin-effect resistance of both legs (ohms/sqrt(Hz)) @param L float inductance of both legs (H) @param G float DC conductance of both legs to ground (S) @param C float capacitance of both legs to ground (F) @param df float dissipation factor (loss-tangent) of capacitance of both legs to ground @param Cm float mutual capacitance (F) @param dfm float dissipation factor (loss-tangent) of mutual capacitance (F) @param Gm float mutual conductance (S) @param Lm float mutual inductance (H) @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to 0). @param scale (optional) float amount to scale the line by (assuming all other values are per unit) If 0 is specified, then an analytic solution is provided otherwise an approximate solution is provided with all parametric values divided into the integer number of sections. """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.SParameters.Devices.TLineTwoPortRLGC import TLineTwoPortRLGC # pragma: include sdp = SystemDescriptionParser() sdp.AddLines([ 'device L 4 mixedmode', 'device R 4 mixedmode', 'device TE 2', 'device TO 2', 'port 1 L 1 2 L 2 3 R 1 4 R 2', 'connect L 3 TO 1', 'connect R 3 TO 2', 'connect L 4 TE 1', 'connect R 4 TE 2' ]) self.m_sspn = SystemSParametersNumeric(sdp.SystemDescription()) self.m_spdl = [ ('TE', TLineTwoPortRLGC(f, R, Rse, L + Lm, G, C, df, Z0, K, scale)), ('TO', TLineTwoPortRLGC(f, R, Rse, L - Lm, G + 2 * Gm, C + 2 * Cm, (C * df + 2 * Cm * dfm) / (C + 2 * Cm), Z0, K, scale)) ] SParameters.__init__(self, f, None, Z0)
def __init__(self, f, R, Rse, L, G, C, df, Z0=50., K=0, scale=1.): """Constructor @param f list of float frequencies @param R float DC series resistance (ohms) @param Rse float series skin-effect resistance (ohms/sqrt(Hz)) @param L float series inductance (H) @param G float DC conductance to ground (S) @param C float capacitance to ground (F) @param df float dissipation factor (loss-tangent) of capacitance to ground @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to zero) @param scale (optional) float amount to scale the line by (assuming all other values are per unit) @note If K=0 is specified, it is modified to a value that will provided a very good numerical approximation. The calculation is such that round-trip propagation time (twice the electrical length) of any one small section is no more than one percent of the fastest possible risetime. """ R = R * scale Rse = Rse * scale L = L * scale G = G * scale C = C * scale df = df K = int(K * scale + 0.5) if K == 0: """max possible electrical length""" Td = math.sqrt(L * C) Rt = 0.45 / f[-1] # fastest risetime """sections such that fraction of risetime less than round trip electrical length of one section""" K = int(math.ceil(Td * 2 / (Rt * self.rtFraction))) self.m_K = K # pragma: silent exclude from SignalIntegrity.Lib.Devices import SeriesZ from SignalIntegrity.Lib.Devices import TerminationG from SignalIntegrity.Lib.SParameters.Devices.TerminationC import TerminationC from SignalIntegrity.Lib.SParameters.Devices.SeriesL import SeriesL from SignalIntegrity.Lib.SParameters.Devices.SeriesRse import SeriesRse from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sdp = SystemDescriptionParser().AddLines([ 'device R 2', 'device Rse 2', 'device L 2', 'device C 1', 'device G 1', 'connect R 2 Rse 1', 'connect Rse 2 L 1', 'connect L 2 G 1 C 1', 'port 1 R 1 2 G 1' ]) self.m_sspn = SystemSParametersNumeric(sdp.SystemDescription()) self.m_sspn.AssignSParameters('R', SeriesZ(R / K, Z0)) self.m_sspn.AssignSParameters('G', TerminationG(G / K, Z0)) self.m_spdl = [('Rse', SeriesRse(f, Rse / K, Z0)), ('L', SeriesL(f, L / K, Z0)), ('C', TerminationC(f, C / K, Z0, df))] SParameters.__init__(self, f, None, Z0)
class TLineDifferentialRLGCBalanced(SParameters): """s-parameters of analytic balanced differential RLGC (telegrapher's) transmission line.""" def __init__(self, f, R, Rse, L, G, C, df, Cm, dfm, Gm, Lm, Z0=50., K=0): """Constructor ports are 1,2,3,4 is +1,-1, +2, -2 @param f list of float frequencies @param R float DC resistance of both legs (ohms) @param Rse float skin-effect resistance of both legs (ohms/sqrt(Hz)) @param L float inductance of both legs (H) @param G float DC conductance of both legs to ground (S) @param C float capacitance of both legs to ground (F) @param df float dissipation factor (loss-tangent) of capacitance of both legs to ground @param Cm float mutual capacitance (F) @param dfm float dissipation factor (loss-tangent) of mutual capacitance (F) @param Gm float mutual conductance (S) @param Lm float mutual inductance (H) @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to 0). If 0 is specified, then an analytic solution is provided otherwise an approximate solution is provided with all parametric values divided into the integer number of sections. """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.SParameters.Devices.TLineTwoPortRLGC import TLineTwoPortRLGC # pragma: include sdp = SystemDescriptionParser() sdp.AddLines([ 'device L 4 mixedmode', 'device R 4 mixedmode', 'device TE 2', 'device TO 2', 'port 1 L 1 2 L 2 3 R 1 4 R 2', 'connect L 3 TO 1', 'connect R 3 TO 2', 'connect L 4 TE 1', 'connect R 4 TE 2' ]) self.m_sspn = SystemSParametersNumeric(sdp.SystemDescription()) self.m_spdl = [ ('TE', TLineTwoPortRLGC(f, R, Rse, L + Lm, G, C, df, Z0, K)), ('TO', TLineTwoPortRLGC(f, R, Rse, L - Lm, G + 2 * Gm, C + 2 * Cm, (C * df + 2 * Cm * dfm) / (C + 2 * Cm), Z0, K)) ] SParameters.__init__(self, f, None, Z0) def __getitem__(self, n): """overloads [n] @return list of list s-parameter matrix for the nth frequency element """ for ds in self.m_spdl: self.m_sspn.AssignSParameters(ds[0], ds[1][n]) return self.m_sspn.SParameters()
class TLineDifferentialRLGCUncoupled(SParameters): """s-parameters of analytic uncoupled differential RLGC (telegrapher's) transmission line.""" def __init__(self,f,Rp,Rsep,Lp,Gp,Cp,dfp,Rn,Rsen,Ln,Gn,Cn,dfn,Z0=50.,K=0): """Constructor ports are 1,2,3,4 is +1,-1, +2, -2 @param f list of float frequencies @param Rp float DC resistance of positive leg (Ohms) @param Rsep float skin-effect resistance of positive leg (Ohms/sqrt(Hz)) @param Lp float inductance of positive leg (H) @param Gp float DC conductance of positive leg to ground (S) @param Cp float capacitance of positive leg to ground (F) @param dfp float dissipation factor (loss-tangent) of capacitance of positive leg to ground @param Rn float DC resistance of negative leg (Ohms) @param Rsen float skin-effect resistance of negative leg (Ohms/sqrt(Hz)) @param Ln float inductance of negative leg (H) @param Gn float DC conductance of negative leg to ground (S) @param Cn float capacitance of negative leg to ground (F) @param dfn float dissipation factor (loss-tangent) of capacitance of negative leg to ground @param Z0 (optional) float reference impedance (defaults to 50 Ohms) @param K (optional) integer number of sections (defaults to 0). If 0 is specified, then an analytic solution is provided otherwise an approximate solution is provided with all parametric values divided into the integer number of sections. """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.SParameters.Devices.TLineTwoPortRLGC import TLineTwoPortRLGC # pragma: include sdp=SystemDescriptionParser() sdp.AddLines(['device TP 2','device TN 2', 'port 1 TP 1 2 TN 1 3 TP 2 4 TN 2']) self.m_sspn=SystemSParametersNumeric(sdp.SystemDescription()) self.m_spdl=[('TP',TLineTwoPortRLGC(f,Rp,Rsep,Lp,Gp,Cp,dfp,Z0,K)), ('TO',TLineTwoPortRLGC(f,Rn,Rsen,Ln,Gn,Cn,dfn,Z0,K))] SParameters.__init__(self,f,None,Z0) def __getitem__(self,n): """overloads [n] @return list of list s-parameter matrix for the nth frequency element """ for ds in self.m_spdl: self.m_sspn.AssignSParameters(ds[0],ds[1][n]) return self.m_sspn.SParameters()
def __init__(self, f, offsetDelay=0.0, offsetZ0=50.0, offsetLoss=0.0, f0=1e9, C0=0.0, C1=0.0, C2=0.0, C3=0.0): """Constructor @param f list of frequencies @param offsetDelay (optional) float electrical length of offset in s (defaults to 0 s) @param offsetZ0 (optional) float real characteristic impedance of offset (defaults to 50 ohms) @param offsetLoss (optional) float loss due to skin-effect defined in Gohms/s at 1 GHz (defaults to 0). @param f0 (optional) float frequency where the offset loss is defined (defaults to 1e9). @param C0 (optional) float polynomial coefficient for capacitance of open termination @param C1 (optional) float polynomial coefficient for capacitance of open termination @param C2 (optional) float polynomial coefficient for capacitance of open termination @param C3 (optional) float polynomial coefficient for capacitance of open termination The result is that the class becomes the base-class SParameters with the s-parameters of a open standard. Termination capacitance polynomial is C0+f*(C1+f*(C2+f*C3)). """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sspn = SystemSParametersNumeric(SystemDescriptionParser().AddLines([ 'device offset 2', 'device C 1', 'port 1 offset 1', 'connect offset 2 C 1' ]).SystemDescription()) offsetSParameters = Offset(f, offsetDelay, offsetZ0, offsetLoss, f0) terminationSParameters = TerminationCPolynomial(f, C0, C1, C2, C3) sp = [] for n in range(len(f)): sspn.AssignSParameters('offset', offsetSParameters[n]) sspn.AssignSParameters('C', terminationSParameters[n]) sp.append(sspn.SParameters()) SParameters.__init__(self, f, sp)
def __init__(self,f,Zd,Td,Zc,Tc,Z0=50.): """Constructor The port numbering is ports 1 and 2 are the plus and minus terminals on one side of the line and ports 3 and 4 are the plus and minus terminals on the other side of the line. @param f list of float frequencies @param Zd float or complex differential mode impedance @param Td float differential (or odd-mode) electrical length (the differential-mode propagation time. @param Zc float or complex common-mode impedance @param Tc float common (or even-mode) electrical length (the common-mode propagation time. @param Z0 (optional) float or complex reference impedance (defaults to 50 Ohms). @note The differential mode impedance is twice the odd-mode impedance.\n The common-mode impedance is half the even-mode impedance.\n @note The model is appropriate for a balanced transmission line.\n @note The s-parameters provided are single-ended. @note This device builds a model internally and only solves the model on each access to __getitem__(). """ import SignalIntegrity.Lib.SParameters.Devices as dev from SignalIntegrity.Lib.Devices.MixedModeConverter import MixedModeConverter from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric self.m_sspn=SystemSParametersNumeric() self.m_spdl=[] self.m_sspn.AddDevice('MM1',4,MixedModeConverter()) self.m_sspn.AddDevice('MM2',4,MixedModeConverter()) self.m_sspn.AddDevice('D',2), self.m_spdl.append(('D',dev.TLineLossless(f,2,Zd/2.,Td,Z0))) self.m_sspn.AddDevice('C',2), self.m_spdl.append(('C',dev.TLineLossless(f,2,Zc*2.,Tc,Z0))) self.m_sspn.ConnectDevicePort('MM1',3,'D',1) self.m_sspn.ConnectDevicePort('MM2',3,'D',2) self.m_sspn.ConnectDevicePort('MM1',4,'C',1) self.m_sspn.ConnectDevicePort('MM2',4,'C',2) self.m_sspn.AddPort('MM1',1,1) self.m_sspn.AddPort('MM1',2,2) self.m_sspn.AddPort('MM2',1,3) self.m_sspn.AddPort('MM2',2,4) SParameters.__init__(self,f,None,Z0)
def __init__(self, f, offsetDelay=0.0, offsetZ0=50.0, offsetLoss=0.0, L0=0.0, L1=0.0, L2=0.0, L3=0.0): """Constructor @param f list of frequencies @param offsetDelay (optional) float electrical length of offset in s (defaults to 0 s) @param offsetZ0 (optional) float real characteristic impedance of offset (defaults to 50 Ohms) @param offsetLoss (optional) float loss due to skin-effect defined in GOhms/s at 1 GHz (defaults to 0). @param L0 (optional) float polynomial coefficient for inductance of short termination @param L1 (optional) float polynomial coefficient for inductance of short termination @param L2 (optional) float polynomial coefficient for inductance of short termination @param L3 (optional) float polynomial coefficient for inductance of short termination The result is that the class becomes the base-class SParameters with the s-parameters of a short standard. Termination inductance polynomial is L0+f*(L1+f*(L2+f*L3)). """ # pragma: silent exclude from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sspn = SystemSParametersNumeric(SystemDescriptionParser().AddLines([ 'device offset 2', 'device L 1', 'port 1 offset 1', 'connect offset 2 L 1' ]).SystemDescription()) offsetSParameters = Offset(f, offsetDelay, offsetZ0, offsetLoss) terminationSParameters = TerminationLPolynomial(f, L0, L1, L2, L3) sp = [] for n in range(len(f)): sspn.AssignSParameters('offset', offsetSParameters[n]) sspn.AssignSParameters('L', terminationSParameters[n]) sp.append(sspn.SParameters()) SParameters.__init__(self, f, sp)
def SParameters(self, solvetype='block'): """compute the s-parameters of the netlist. @param solvetype (optional) string how to solve it. (defaults to 'block'). @return instance of class SParameters as the solution of the network. @remark valid solvetype strings are: - 'block' - use the block matrix solution method. - 'direct' - use the direct method. 'block' is faster and preferred, but direct is provided as an alternative and for testing. (Previously, instances were found where the block method failed, but the direct method did not - but this possibility is thought to be impossible now. """ # pragma: silent exclude if self.CheckCache(): self.CallBack(100.0) return self.sf # pragma: include self.SystemDescription() self.m_sd.CheckConnections() spc = self.m_spc result = [] for n in range(len(self.m_f)): for d in range(len(spc)): if not spc[d][0] is None: self.m_sd.AssignSParameters(spc[d][0], spc[d][1][n]) result.append( SystemSParametersNumeric( self.m_sd).SParameters(solvetype=solvetype)) # pragma: silent exclude if self.HasACallBack(): progress = self.m_f[n] / self.m_f[-1] * 100.0 if not self.CallBack(progress): raise SignalIntegrityExceptionSParameters( 'calculation aborted') # pragma: include self.sf = SParameters(self.m_f, result) # pragma: silent exclude if hasattr(self, 'delayDict'): td = [ self.delayDict[p + 1] if p + 1 in self.delayDict else 0.0 for p in range(self.sf.m_P) ] self.sf = PeeledLaunches(self.sf, td, method='exact') self.sf = SParametersParser(self.sf, self.m_ul) self.CacheResult() # pragma: include return self.sf
def DutUnCalculationAlternate(self,S,portList=None): """Un-calcualates the DUT.\n This calculates the expected raw measured DUT based on the DUT actually calculated.\n @see DutCalculation @param S instance of class SParameters of measured DUT from these error-terms. @param portList (optional) list of zero based port numbers used for the DUT calcualtion @return instance of class SParameters of the raw measured s-parameters that calculated this DUT @remark If the portList is None, then it assumed to be a list [0,1,2,P-1] where P is the number of ports in sRaw, otherwise ports can be specified where the DUT is connected. @deprecated This method utilizes fixtures and embeds them. Originally, I could not figure out how to do this with just the error-terms. This was figured out finally and is more efficient, but this method is retained for comparison of results. @see DutUnCalculation """ self.CalculateErrorTerms() if portList is None: portList=[p for p in range(self.ports)] ports=len(portList) sspn=SystemSParametersNumeric() sspn.AddDevice('F',2*ports) sspn.AddDevice('D',ports) for p in range(ports): sspn.AddPort('F',p+1,p+1) sspn.ConnectDevicePort('F',ports+p+1,'D',p+1) rd=[None for n in range(len(self.f))] fixtureList=self.Fixtures(portList) for n in range(len(self.f)): rm=[[None for c in range(ports)] for r in range(ports)] sspn.AssignSParameters('D',S[n]) for p in range(ports): sspn.AssignSParameters('F',fixtureList[p][n]) spp=sspn.SParameters() for r in range(ports): rm[r][p]=spp[r][p] rd[n]=rm return SParameters(self.f,rd)
def __init__(self,f, Rp, Rsep, Lp, Gp, Cp, dfp, Rn, Rsen, Ln, Gn, Cn, dfn, Cm, dfm, Gm, Lm, Z0=50., K=0, scale=1.): """Constructor ports are 1,2,3,4 is +1,-1, +2, -2 @param f list of float frequencies @param Rp float DC resistance of positive leg (ohms) @param Rsep float skin-effect resistance of positive leg (ohms/sqrt(Hz)) @param Lp float inductance of positive leg (H) @param Gp float DC conductance of positive leg to ground (S) @param Cp float capacitance of positive leg to ground (F) @param dfp float dissipation factor (loss-tangent) of capacitance of positive leg to ground @param Rn float DC resistance of negative leg (ohms) @param Rsen float skin-effect resistance of negative leg (ohms/sqrt(Hz)) @param Ln float inductance of negative leg (H) @param Gn float DC conductance of negative leg to ground (S) @param Cn float capacitance of negative leg to ground (F) @param dfn float dissipation factor (loss-tangent) of capacitance of negative leg to ground @param Cm float mutual capacitance (F) @param dfm float dissipation factor (loss-tangent) of mutual capacitance (F) @param Gm float mutual conductance (S) @param Lm float mutual inductance (H) @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to 0) @param scale (optional) float amount to scale the line by (assuming all other values are per unit) @note If K=0 is specified, it is modified to a value that will provided a very good numerical approximation. The calculation is such that round-trip propagation time (twice the electrical length) of any one small section is no more than one percent of the fastest possible risetime. """ Rp=Rp*scale; Rsep=Rsep*scale; Lp=Lp*scale; Gp=Gp*scale; Cp=Cp*scale; dfp=dfp Rn=Rn*scale; Rsen=Rsen*scale; Ln=Ln*scale; Gn=Gn*scale; Cn=Cn*scale; dfn=dfn Cm=Cm*scale; dfm=dfm; Gm=Gm*scale; Lm=Lm*scale K=int(K*scale+0.5) if K==0: """max possible electrical length""" Td=math.sqrt((max(Lp,Ln)+Lm)*(max(Cp,Cn)+2*Cm)) Rt=0.45/f[-1] # fastest risetime """sections such that fraction of risetime less than round trip electrical length of one section""" K=int(math.ceil(Td*2/(Rt*self.rtFraction))) self.m_K=K # pragma: silent exclude from SignalIntegrity.Lib.Devices import SeriesG from SignalIntegrity.Lib.Devices import SeriesZ from SignalIntegrity.Lib.Devices import TerminationG import SignalIntegrity.Lib.SParameters.Devices as dev from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sdp=SystemDescriptionParser().AddLines([ 'device rsep 2','device rp 2','device lp 2','device gp 1','device cp 1', 'device rsen 2','device rn 2','device ln 2','device gn 1','device cn 1', 'device lm 4','device gm 2','device cm 2', 'connect rp 2 rsep 1','connect rsep 2 lp 1', 'connect rn 2 rsen 1','connect rsen 2 ln 1', 'connect lp 2 lm 1','connect ln 2 lm 3', 'connect lm 2 gp 1 cp 1 gm 1 cm 1','connect lm 4 gn 1 cn 1 gm 2 cm 2', 'port 1 rp 1 2 rn 1 3 lm 2 4 lm 4']) self.m_sspn=SystemSParametersNumeric(sdp.SystemDescription()) self.m_sspn.AssignSParameters('rp',SeriesZ(Rp/K,Z0)) self.m_sspn.AssignSParameters('gp',TerminationG(Gp/K,Z0)) self.m_sspn.AssignSParameters('rn',SeriesZ(Rn/K,Z0)) self.m_sspn.AssignSParameters('gn',TerminationG(Gn/K,Z0)) self.m_sspn.AssignSParameters('gm',SeriesG(Gm/K,Z0)) self.m_spdl=[('rsep',dev.SeriesRse(f,Rsep/K,Z0)), ('lp',dev.SeriesL(f,Lp/K,Z0)),('cp',dev.TerminationC(f,Cp/K,Z0,dfp)), ('rsen',dev.SeriesRse(f,Rsen/K,Z0)),('ln',dev.SeriesL(f,Ln/K,Z0)), ('cn',dev.TerminationC(f,Cn/K,Z0,dfn)),('lm',dev.Mutual(f,Lm/K,Z0)), ('cm',dev.SeriesC(f,Cm/K,Z0,dfm))] SParameters.__init__(self,f,None,Z0)
class TLineDifferentialRLGCApproximate(SParameters): """s-parameters of differential RLGC (telegrapher's) transmission line calculated by approximating distributed parameters with a finite number of sections specified.""" rtFraction = .01 def __init__(self, f, Rp, Rsep, Lp, Gp, Cp, dfp, Rn, Rsen, Ln, Gn, Cn, dfn, Cm, dfm, Gm, Lm, Z0=50., K=0): """Constructor ports are 1,2,3,4 is +1,-1, +2, -2 @param f list of float frequencies @param Rp float DC resistance of positive leg (ohms) @param Rsep float skin-effect resistance of positive leg (ohms/sqrt(Hz)) @param Lp float inductance of positive leg (H) @param Gp float DC conductance of positive leg to ground (S) @param Cp float capacitance of positive leg to ground (F) @param dfp float dissipation factor (loss-tangent) of capacitance of positive leg to ground @param Rn float DC resistance of negative leg (ohms) @param Rsen float skin-effect resistance of negative leg (ohms/sqrt(Hz)) @param Ln float inductance of negative leg (H) @param Gn float DC conductance of negative leg to ground (S) @param Cn float capacitance of negative leg to ground (F) @param dfn float dissipation factor (loss-tangent) of capacitance of negative leg to ground @param Cm float mutual capacitance (F) @param dfm float dissipation factor (loss-tangent) of mutual capacitance (F) @param Gm float mutual conductance (S) @param Lm float mutual inductance (H) @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to 0) @note If K=0 is specified, it is modified to a value that will provided a very good numerical approximation. The calculation is such that round-trip propagation time (twice the electrical length) of any one small section is no more than one percent of the fastest possible risetime. """ if K == 0: """max possible electrical length""" Td = math.sqrt((max(Lp, Ln) + Lm) * (max(Cp, Cn) + 2 * Cm)) Rt = 0.45 / f[-1] # fastest risetime """sections such that fraction of risetime less than round trip electrical length of one section""" K = int(math.ceil(Td * 2 / (Rt * self.rtFraction))) self.m_K = K # pragma: silent exclude from SignalIntegrity.Lib.Devices import SeriesG from SignalIntegrity.Lib.Devices import SeriesZ from SignalIntegrity.Lib.Devices import TerminationG import SignalIntegrity.Lib.SParameters.Devices as dev from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sdp = SystemDescriptionParser().AddLines([ 'device rsep 2', 'device rp 2', 'device lp 2', 'device gp 1', 'device cp 1', 'device rsen 2', 'device rn 2', 'device ln 2', 'device gn 1', 'device cn 1', 'device lm 4', 'device gm 2', 'device cm 2', 'connect rp 2 rsep 1', 'connect rsep 2 lp 1', 'connect rn 2 rsen 1', 'connect rsen 2 ln 1', 'connect lp 2 lm 1', 'connect ln 2 lm 3', 'connect lm 2 gp 1 cp 1 gm 1 cm 1', 'connect lm 4 gn 1 cn 1 gm 2 cm 2', 'port 1 rp 1 2 rn 1 3 lm 2 4 lm 4' ]) self.m_sspn = SystemSParametersNumeric(sdp.SystemDescription()) self.m_sspn.AssignSParameters('rp', SeriesZ(Rp / K, Z0)) self.m_sspn.AssignSParameters('gp', TerminationG(Gp / K, Z0)) self.m_sspn.AssignSParameters('rn', SeriesZ(Rn / K, Z0)) self.m_sspn.AssignSParameters('gn', TerminationG(Gn / K, Z0)) self.m_sspn.AssignSParameters('gm', SeriesG(Gm / K, Z0)) self.m_spdl = [('rsep', dev.SeriesRse(f, Rsep / K, Z0)), ('lp', dev.SeriesL(f, Lp / K, Z0)), ('cp', dev.TerminationC(f, Cp / K, Z0, dfp)), ('rsen', dev.SeriesRse(f, Rsen / K, Z0)), ('ln', dev.SeriesL(f, Ln / K, Z0)), ('cn', dev.TerminationC(f, Cn / K, Z0, dfn)), ('lm', dev.Mutual(f, Lm / K, Z0)), ('cm', dev.SeriesC(f, Cm / K, Z0, dfm))] SParameters.__init__(self, f, None, Z0) def __getitem__(self, n): """overloads [n] @return list of list s-parameter matrix for the nth frequency element """ for ds in self.m_spdl: self.m_sspn.AssignSParameters(ds[0], ds[1][n]) sp = self.m_sspn.SParameters() if sp == 1: return sp lp = [1, 2] rp = [3, 4] return T2S(linalg.matrix_power(S2T(sp, lp, rp), self.m_K), lp, rp)
class TLineTwoPortRLGCApproximate(SParameters): """s-parameters of two port RLGC (telegrapher's) transmission line calculated by approximating distributed parameters with a finite number of sections specified.""" rtFraction = .01 def __init__(self, f, R, Rse, L, G, C, df, Z0=50., K=0): """Constructor @param f list of float frequencies @param R float DC series resistance (Ohms) @param Rse float series skin-effect resistance (Ohms/sqrt(Hz)) @param L float series inductance (H) @param G float DC conductance to ground (S) @param C float capacitance to ground (F) @param df float dissipation factor (loss-tangent) of capacitance to ground @param Z0 (optional) float reference impedance (defaults to 50 Ohms) @param K (optional) integer number of sections (defaults to zero) @note If K=0 is specified, it is modified to a value that will provided a very good numerical approximation. The calculation is such that round-trip propagation time (twice the electrical length) of any one small section is no more than one percent of the fastest possible risetime. """ if K == 0: """max possible electrical length""" Td = math.sqrt(L * C) Rt = 0.45 / f[-1] # fastest risetime """sections such that fraction of risetime less than round trip electrical length of one section""" K = int(math.ceil(Td * 2 / (Rt * self.rtFraction))) self.m_K = K # pragma: silent exclude from SignalIntegrity.Lib.Devices import SeriesZ from SignalIntegrity.Lib.Devices import TerminationG from SignalIntegrity.Lib.SParameters.Devices.TerminationC import TerminationC from SignalIntegrity.Lib.SParameters.Devices.SeriesL import SeriesL from SignalIntegrity.Lib.SParameters.Devices.SeriesRse import SeriesRse from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include sdp = SystemDescriptionParser().AddLines([ 'device R 2', 'device Rse 2', 'device L 2', 'device C 1', 'device G 1', 'connect R 2 Rse 1', 'connect Rse 2 L 1', 'connect L 2 G 1 C 1', 'port 1 R 1 2 G 1' ]) self.m_sspn = SystemSParametersNumeric(sdp.SystemDescription()) self.m_sspn.AssignSParameters('R', SeriesZ(R / K, Z0)) self.m_sspn.AssignSParameters('G', TerminationG(G / K, Z0)) self.m_spdl = [('Rse', SeriesRse(f, Rse / K, Z0)), ('L', SeriesL(f, L / K, Z0)), ('C', TerminationC(f, C / K, Z0, df))] SParameters.__init__(self, f, None, Z0) def __getitem__(self, n): """overloads [n] @return list of list s-parameter matrix for the nth frequency element """ # pragma: silent exclude from numpy import linalg from SignalIntegrity.Lib.Conversions import S2T from SignalIntegrity.Lib.Conversions import T2S # pragma: include for ds in self.m_spdl: self.m_sspn.AssignSParameters(ds[0], ds[1][n]) sp = self.m_sspn.SParameters() return T2S(linalg.matrix_power(S2T(sp), self.m_K))
def __init__(self,f, wires, R, Rse, df, Cm, Gm, Lm, Z0=50., K=0, scale=1.): """Constructor ports are 1,2,3,4, etc. on left and W, W+1, W+2, W+4, etc. on right where W=wires and wire 1 is port 1 to P, wire 2 is port 2 to (P+1), etc. This is a P=2*w port device. @param f list of float frequencies @param wires integer number of wires @param R list of float DC resistance of wire (ohms) @param Rse list of float skin-effect resistance of wire (ohms/sqrt(Hz)) @param df list of list of float dissipation factor (loss-tangent) of capacitance (unitless) @param C list of list of float mutual capacitance (self capacitance on diagonal) (F) @param G list of list of float mutual conductance (self conductance on diagonal) (S) @param L list of list of float mutual inductance (self inductance on diagonal) (H) @param Z0 (optional) float reference impedance (defaults to 50 ohms) @param K (optional) integer number of sections (defaults to 0) @param scale (optional) float amount to scale the line by (assuming all other values are per unit) @note If K=0 is specified, it is modified to a value that will provided a very good numerical approximation. The calculation is such that round-trip propagation time (twice the electrical length) of any one small section is no more than one percent of the fastest possible risetime. """ R=[r*scale for r in R]; Rse=[rse*scale for rse in Rse]; Cm=[[cm*scale for cm in cmr] for cmr in Cm]; Gm=[[gm*scale for gm in gmr] for gmr in Gm]; Lm=[[lm*scale for lm in lmr] for lmr in Lm] K=int(K*scale+0.5) if K==0: maxL=0.0; maxLm=0.0 for r in range(len(Lm)): for c in range(len(Lm[r])): if r==c: maxL=max(maxL,Lm[r][c]) else: maxLm=max(maxLm,Lm[r][c]) maxC=0.0; maxCm=0.0 for r in range(len(Cm)): for c in range(len(Cm[r])): if r==c: maxC=max(maxC,Cm[r][c]) else: maxCm=max(maxCm,Cm[r][c]) """max possible electrical length and fastest risetime""" Td=math.sqrt((maxL+maxLm)*(maxC+2*maxCm)); Rt=0.45/f[-1] """sections such that fraction of risetime less than round trip electrical length of one section""" K=int(math.ceil(Td*2/(Rt*self.rtFraction))) self.m_K=K # build the netlist # pragma: silent exclude from SignalIntegrity.Lib.Devices import SeriesG from SignalIntegrity.Lib.Devices import SeriesZ from SignalIntegrity.Lib.Devices import TerminationG import SignalIntegrity.Lib.SParameters.Devices as dev from SignalIntegrity.Lib.SystemDescriptions.SystemSParametersNumeric import SystemSParametersNumeric from SignalIntegrity.Lib.Parsers.SystemDescriptionParser import SystemDescriptionParser # pragma: include # first all of the devices sdp=SystemDescriptionParser().AddLines(['device R_'+str(w+1)+' 2' for w in range(wires)]) sdp.AddLines(['device Rse_'+str(w+1)+' 2' for w in range(wires)]) sdp.AddLines(['device L_'+str(w+1)+' 2' for w in range(wires)]) sdp.AddLines(['device G_'+str(w+1)+' 1' for w in range(wires)]) sdp.AddLines(['device C_'+str(w+1)+' 1' for w in range(wires)]) for w in range(wires-1): for o in range(w+1,wires): suffix='_'+str(w+1)+'_'+str(o+1) sdp.AddLines(['device M'+suffix+' 4','device C'+suffix+' 2','device G'+suffix+' 2']) sdp.AddLines(['port '+str(w+1)+' R_'+str(w+1)+' 1' for w in range(wires)]) sdp.AddLines(['port '+str(w+wires+1)+' C_'+str(w+1)+' 1' for w in range(wires)]) # connect all of the devices sdp.AddLines(['connect R_'+str(w+1)+' 2 Rse_'+str(w+1)+' 1' for w in range(wires)]) sdp.AddLines(['connect Rse_'+str(w+1)+' 2 L_'+str(w+1)+' 1' for w in range(wires)]) for w in range(wires): DeviceFromString='L_'+str(w+1) DeviceFromPin=2 CapacitorConductanceConnectionString='C_'+str(w+1)+' 1 G_'+str(w+1)+' 1' for o in range(wires): if (o==w): continue if (o>w): actualFrom=w actualTo=o actualInputPin=1 nextOutputPin=2 CapacitorConductanceConnectionString+=' C_'+str(w+1)+'_'+str(o+1)+' 1 G_'+str(w+1)+'_'+str(o+1)+' 1' else: actualFrom=o actualTo=w actualInputPin=3 nextOutputPin=4 CapacitorConductanceConnectionString+=' C_'+str(o+1)+'_'+str(w+1)+' 2 G_'+str(o+1)+'_'+str(w+1)+' 2' DeviceToString='M_'+str(actualFrom+1)+'_'+str(actualTo+1) sdp.AddLine('connect '+DeviceFromString+' '+str(DeviceFromPin)+' '+DeviceToString+' '+str(actualInputPin)) DeviceFromString=DeviceToString DeviceFromPin=nextOutputPin # finally, connect this last device output to the capacitances and conductances sdp.AddLine('connect '+DeviceFromString+' '+str(DeviceFromPin)+' '+CapacitorConductanceConnectionString) # make the system description and assign the s-parameters self.m_sspn=SystemSParametersNumeric(sdp.SystemDescription()) self.NetListLines=sdp.m_lines # frequency independent get assigned directly for w in range(wires): self.m_sspn.AssignSParameters('R_'+str(w+1),SeriesZ(R[w]/K,Z0)) self.m_sspn.AssignSParameters('G_'+str(w+1),TerminationG(Gm[w][w]/K,Z0)) for o in range(w+1,wires): self.m_sspn.AssignSParameters('G_'+str(w+1)+'_'+str(o+1),SeriesG(Gm[o][w]/K,Z0)) # [o][w] not [w][o] to allow lower triangular # now for frequency dependent ones self.m_spdl=[] for w in range(wires): self.m_spdl.append(('Rse_'+str(w+1),dev.SeriesRse(f,Rse[w]/K,Z0))) self.m_spdl.append(('C_'+str(w+1),dev.TerminationC(f,Cm[w][w]/K,Z0,df[w][w]))) self.m_spdl.append(('L_'+str(w+1),dev.SeriesL(f,Lm[w][w]/K,Z0))) for o in range(w+1,wires): self.m_spdl.append(('M_'+str(w+1)+'_'+str(o+1),dev.Mutual(f,Lm[o][w]/K,Z0))) # see note about [o][w] order above self.m_spdl.append(('C_'+str(w+1)+'_'+str(o+1),dev.SeriesC(f,Cm[o][w]/K,Z0,df[o][w]))) SParameters.__init__(self,f,None,Z0)