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)
Exemplo n.º 2
0
    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)