Code covered by the BSD License  

Highlights from
INTERFACE BETWEEN MATLAB AND CADENCE FOR MACRO-MODEL EXTRACTION

image thumbnail
from INTERFACE BETWEEN MATLAB AND CADENCE FOR MACRO-MODEL EXTRACTION by Philippe BENABES
launch cadence analog simulations from Matlab and extract a macromodel of linear analog functions

sub_fct_str=tf_decomp_real(Num, Den)
%---------------------------------------------------
% Ce programme est la propriete exclusive de SUPELEC
% Tout  usage  non  authorise  ou reproduction de ce
% programme est strictement defendu. 
% Copyright  (c) 2010  SUPELEC  Departement SSE
% Tous droits reserves
%---------------------------------------------------
%
% fichier : tf_decomp_real.m
% auteur  : P.BENABES & C.TUGUI 
% Copyright (c) 2010 SUPELEC
%
%---------------------------------------------------
%
% DESCRIPTION DU MODULE :
%   
%
% MODULES UTILISES :
%
%---------------------------------------------------


function sub_fct_str=tf_decomp_real(Num, Den)

% Find the decomposition of a transfer functions of type
%                         nb-1         nb-2
%             B(s)   b(1)s     +  b(2)s     + ... +  b(nb)
%      H(s) = ---- = -------------------------------------
%                         na-1         na-2
%             A(s)   a(1)s     +  a(2)s     + ... +  a(na)
%
% into a product of real transfer functions of orders 1 and 2:

%                                           2 
%              (s-z1) (s-z2)     (s-zn)  a1s + b1s + c1   
%      H(s) =  ------*------*...*------* --------------*...
%              (s-p1) (s-p2)     (s-pn)     2
%                                        d1s + e1s + f1  

sub_fct_str=[];

% Find the poles, zeros and gain of TF

%[z,p,gn] = tf2zp(Num,Den);
z=roots(Num);
p=roots(Den);

if isempty(z)&&isempty(p)
    sub_fct_str.Num=Num;
    sub_fct_str.Den=Den;
else
    gn=abs(Num(end)/Den(end)) ;     %% gain
    gs=sign(Num(end)/Den(end)) ;    %% sign

    % Find real p/z
    zreal=[];
    zcmpx=[];
    zreal_n=0;
    for i=1:size(z,1)
        if isreal(z(i))
            zreal=[zreal;z(i)];
            zreal_n=zreal_n+1;
        else
            zcmpx=[zcmpx;z(i)];
        end
    end

    preal=[];
    pcmpx=[];
    preal_n=0;
    for i=1:size(p,1)
        if isreal(p(i))
            preal=[preal;p(i)];
            preal_n=preal_n+1;
        else
            pcmpx=[pcmpx;p(i)];
        end
    end

    % Maximum number of ord1 functions will be the minimum real p/z
    maxord1=min(zreal_n,preal_n);

    % Maximum number of ord2 pure complex functions will be the minimum complex p/z
    zcmpx_n=size(z,1)-zreal_n;
    pcmpx_n=size(p,1)-preal_n;
    maxord2cmpx=min(zcmpx_n,pcmpx_n);

    % Test pairs of complex p/z
    if (~mod(zcmpx_n,2))&&(~mod(pcmpx_n,2))

        ind=1;
        elim=[];
        % Now compute all ord1 functions
        for i=1:maxord1
            %Use the gain gn for the first function
            if i==1
                [Num_subf,Den_subf] = zp2tf(zreal(i),preal(i),1);
                elim=[elim i];
            else %Use gain=1 for the others
                [Num_subf,Den_subf] = zp2tf(zreal(i),preal(i),1);
                elim=[elim i];
            end

            [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

            sub_fct_str(ind).Num=Num_subf_norm;
            sub_fct_str(ind).Den=Den_subf_norm;
            ind=ind+1;
        end

        if ~isempty(zreal)
            zreal=zreal(setdiff(1:size(zreal,1),elim));
        end
        if ~isempty(preal)
            preal=preal(setdiff(1:size(preal,1),elim));
        end

        %Eliminate complex-conjugated values
        if zcmpx_n>0
            elim=[];
            for k=1:zcmpx_n-1
                for l=k+1:zcmpx_n
                    if zcmpx(l)==conj(zcmpx(k))
                        elim=[elim l];
                    end
                end
            end
            zcmpx=zcmpx(setdiff(1:size(zcmpx,1),elim));
        end

        if pcmpx_n>0
            elim=[];
            for k=1:pcmpx_n-1
                for l=k+1:pcmpx_n
                    if pcmpx(l)==conj(pcmpx(k))
                        elim=[elim l];
                    end
                end
            end
            pcmpx=pcmpx(setdiff(1:size(pcmpx,1),elim));
        end

        % Now compute all ord2 pure complex functions
        elim=[];
        for i=1:maxord2cmpx/2

            [Num_subf,Den_subf] = zp2tf([zcmpx(i); conj(zcmpx(i))] ,[pcmpx(i); conj(pcmpx(i))] ,1);
            elim=[elim i];

            [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

            sub_fct_str(ind).Num=Num_subf_norm;
            sub_fct_str(ind).Den=Den_subf_norm;

            ind=ind+1;
        end

        zcmpx=zcmpx(setdiff(1:size(zcmpx,1),elim));
        pcmpx=pcmpx(setdiff(1:size(pcmpx,1),elim));

        % Now, the remaining singularities can be found in zcmpx pcmpx zreal preal

        % Form mixed functions with all the remaining complex singularities

        while ~isempty(zcmpx)

            if size(preal,1)>=2

                [Num_subf,Den_subf] = zp2tf([zcmpx(1); conj(zcmpx(1))] ,[preal(1); preal(2)] ,1);

                [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

                sub_fct_str(ind).Num=Num_subf_norm;
                sub_fct_str(ind).Den=Den_subf_norm;

                ind=ind+1;

                zcmpx=zcmpx(setdiff(1:size(zcmpx,1),1));
                preal=preal(setdiff(1:size(preal,1),[1 2]));

            elseif size(preal,1)==1

                [Num_subf,Den_subf] = zp2tf([zcmpx(1); conj(zcmpx(1))] , preal(1) ,1);

                [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

                sub_fct_str(ind).Num=Num_subf_norm;
                sub_fct_str(ind).Den=Den_subf_norm;
                ind=ind+1;

                zcmpx=zcmpx(setdiff(1:size(zcmpx,1),1));
                preal=preal(setdiff(1:size(preal,1),1));

            else

                [Num_subf,Den_subf] = zp2tf([zcmpx(1); conj(zcmpx(1))] , 1 ,1);

                [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

                sub_fct_str(ind).Num=Num_subf_norm;
                sub_fct_str(ind).Den=Den_subf_norm;
                ind=ind+1;

                zcmpx=zcmpx(setdiff(1:size(zcmpx,1),1));

            end

        end

        while ~isempty(pcmpx)

            if size(zreal,1)>=2
                [Num_subf,Den_subf] = zp2tf([zreal(1); zreal(2)] ,[pcmpx(1); conj(pcmpx(1))] ,1);

                [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

                sub_fct_str(ind).Num=Num_subf_norm;
                sub_fct_str(ind).Den=Den_subf_norm;

                ind=ind+1;

                pcmpx=pcmpx(setdiff(1:size(pcmpx,1),1));
                zreal=zreal(setdiff(1:size(zreal,1),[1 2]));

            elseif size(zreal,1)==1

                [Num_subf,Den_subf] = zp2tf(zreal(1) ,[pcmpx(1); conj(pcmpx(1))] ,1);

                [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

                sub_fct_str(ind).Num=Num_subf_norm;
                sub_fct_str(ind).Den=Den_subf_norm;

                ind=ind+1;

                pcmpx=pcmpx(setdiff(1:size(pcmpx,1),1));
                zreal=zreal(setdiff(1:size(zreal,1),1));

            else

                [Num_subf,Den_subf] = zp2tf(1 ,[pcmpx(1); conj(pcmpx(1))]  ,1);

                [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

                sub_fct_str(ind).Num=Num_subf_norm;
                sub_fct_str(ind).Den=Den_subf_norm;

                ind=ind+1;

                pcmpx=pcmpx(setdiff(1:size(pcmpx,1),1));

            end

        end

        % Form ord1 functions with all the remaining real singularities

        while ~isempty(zreal)

            %[Num_subf,Den_subf] = zp2tf(zreal(1), 1 ,1);
            Num_subf=[1 -zreal(1)] ;
            Den_subf=[1] ;

            [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

            sub_fct_str(ind).Num=Num_subf_norm;
            sub_fct_str(ind).Den=Den_subf_norm;

            ind=ind+1;

            zreal=zreal(setdiff(1:size(zreal,1),1));

        end

        while ~isempty(preal)

            %[Num_subf,Den_subf] = zp2tf(1, preal(1) ,1);
            Num_subf=[1] ;
            Den_subf=[1 -preal(1)] ;

            [Num_subf_norm Den_subf_norm]=norm_sfunct_dc(Num_subf,Den_subf);

            sub_fct_str(ind).Num=Num_subf_norm;
            sub_fct_str(ind).Den=Den_subf_norm;

            ind=ind+1;

            preal=preal(setdiff(1:size(preal,1),1));

        end

    else

        warndlg('Badly scaled transfer function.The function was not decomposed.','TF decomposition error');

        sub_fct_str(1).Num=Num; 
        sub_fct_str(1).Den=Den;

    end

    for k=1:length(sub_fct_str)
        sub_fct_str(k).Num=sub_fct_str(k).Num*(gn^(1/length(sub_fct_str))) ;
    end
    sub_fct_str(1).Num=sub_fct_str(1).Num*gs ;
end
return;        

Contact us at files@mathworks.com