Tool for Removing R11 DSP Blockset Blocks from Models

by

 

27 Oct 2006 (Updated )

The attached script and document help you remove all R11 DSP Blockset blocks from your models.

replace_r11_blocks(system, newsystem)
function replace_r11_blocks(system, newsystem)
% REPLACE_R11_BLOCKS('OLD_MODEL', 'NEW_MODEL')
%    Replaces all R11 DSP Blockset blocks in 'OLD_MODEL' with
%    current Signal Processing Blockset blocks.
%
%    This script does not allow you to overwrite your old model.
%    You must specify a new model name for argument 'NEW_MODEL'.
%    Note: Additional changes might be necessary to make the model
%    fully functional.
%    See Removing_R11_blocks_from_Simulink_Models.doc for suggestions.

% Copyright 2006 The MathWorks, Inc.
% $Revision$ $Date$

    document_name = 'Removing_R11_blocks_from_Simulink_Models.doc';

    if (nargin < 2)
        help replace_r11_blocks;
        return;
    end
    
    v = version;
    idx = strfind(v, 'R2');
    year = str2num(v((idx+1):(idx+4)));
    if (year > 2006)
        fprintf('   This script cannot be used in version %s of MATLAB.\n', v);
        fprintf('   You must use a release of MATLAB that supports the R11 DSP Blockset blocks.\n');
        fprintf('   The last release with this support is R2006b.\n');
        fprintf('   See %s for further information.\n', document_name);
        return;   
    end
    
    if strcmp(system, newsystem) 
        fprintf('    This script does not allow you to overwrite your old model.\n');
        fprintf('    You must specify a new model name for argument ''NEW_MODEL''.\n');
        return;
    end

    load_simulink;
    load_system(system);
    
    blks = libinfo(system);
    
    [disabled references] = search_for_r11(blks);
    
    % Note: script will re-enable any disabled R11 block links as it
    % replaces those blocks to current blocks. Hence, don't report
    % anything about disabled links.
   
    % Analyse model and report to user
    if references == 0
        fprintf('     Model %s does not contain any R11 blocks.\n', system);
        fprintf('     Conversion is not necessary.\n');
        return;
    end
    
    % First, replace any filter design blocks
    messages = replace_filter_design_blocks(system);
    
    sys = system;
    saved = 0;
    
    % If any filter design blocks were replaced, there will be a message
    % In this case, it is necessary to save the model before replacing
    % any other R11 blocks.
    if size(messages) > 0
        save_system(system, newsystem);
        close_system(newsystem);
        load_system(newsystem);
         blks = libinfo(newsystem);
        sys = newsystem;
        saved = 1;
    end       
    
    [disabled references] = search_for_r11(blks);
    if references == 0
        % Filter design blocks were replaced earlier. No other R11
        % blocks were found. Finish up and return.
        fprintf('    Model %s contains R11 blocks and has been converted.\n', system);
        fprintf('    The updated model %s contains current Signal Processing Blockset blocks.\n',newsystem);
        if size(messages, 2) > 0
            fprintf('    The following information will help in completing the conversion of the model:\n');
            fprintf('%s',messages);
        end
        fprintf('\n   Additional changes might be necessary to make the model\n');
        fprintf('   fully functional.\n');
        fprintf('   See %s for suggestions.\n', document_name);
        return;
    end
    
    ref_table = Get_Reference_table();
    r11_blocks = find_blocks_to_replace(blks, ref_table);
    
    saved_params = [];
    [messages saved_params sybsys_to_break_links] = ...
        replace_R11_Blocks(r11_blocks, saved_params, ref_table, messages);        
    
    % Update the model. This will, unfortunately, burn through changing
    % parameter values.
    try
        set_param(sys, 'SimulationCommand', 'update');
    catch
        % Filter out some errors that can't be helped
        errors = check_last_error();
        if size(errors,2)        
            fprintf('     During model update:\n%s\n',errors);
        end
    end
    
    % Need to break links to partial unbuffer subsystem replacements
    break_replacement_links(sybsys_to_break_links);
    
    % Restore the parameter values that were replaced by lib block defaults
    restore_parameters(saved_params);
    
    if saved == 0
        save_system(system, newsystem);
        close_system(newsystem);
        load_system(newsystem);                      
        open_system(system);   
        open_system(newsystem);
    else
        save_system(newsystem);
        close_system(newsystem);
        load_system(newsystem);                      
        open_system(system);
        open_system(newsystem);
    end       
        
    fprintf('    Model %s contains R11 blocks and has been converted.\n', system);
    fprintf('    The updated model %s contains current Signal Processing Blockset blocks.\n',newsystem);
    if size(messages, 2) > 0
        fprintf('    The following information will help in completing the conversion of the model:\n');
        fprintf('%s',messages);
    end
    fprintf('\n   Additional changes might be necessary to make the model\n');
    fprintf('   fully functional.\n');
    fprintf('   See %s for suggestions.\n', document_name);
end

function [messages saved_params sybsys_to_break_links] = ...
    replace_R11_Blocks(blks, saved_params, ref_table, messages)
% Replace R11 blocks that need special treatment   
   sybsys_to_break_links = [];
   k = 1;
   m = 1;
   for i=1:1:size(blks(:))
       rblock = blks{i}.ReferenceBlock;
       switch rblock
           % Special handling of subsystems, reset ports, etc.
           case ['dspbuff2/Partial', char(10), 'Unbuffer']
               block = blks{i}.Block;
               set_param(block, 'ReferenceBlock', ['dsp_r11_replacements/Partial', char(10), 'Unbuffer']);
               sybsys_to_break_links{m} = block;
               m = m + 1;
               % Get parameter values of R11 Partial Unbuffer block               
               N = get_param(block, 'N');
               N1 = get_param(block, 'N1');
               N2 = get_param(block, 'N2');
               ic = get_param(block, 'ic');
               num_chans = get_param(block, 'num_chans');               
               % Compute and set parameters to blocks in subsystem
               % replacement: Reshape1->Submatrix->Unbuffer->Reshape2          
               subBlock = [block, '/Reshape1'];
               saved_params{k} = {subBlock, {'OutputDimensionality'}, ...
                   {'Customize (N-D)'}};
               saved_params{k+1} = {subBlock, {'OutputDimensions'}, ...
                   {['[',N,' ',num_chans,']']}};
               subBlock = [block, '/Reshape2'];
               saved_params{k+2} = {subBlock, {'OutputDimensionality'}, ...
                   {'1-D array'}};
               saved_params{k+3} = {subBlock, {'OutputDimensions'}, {'[1,1]'}};
               subBlock = [block, '/Submatrix'];
               saved_params{k+4} = {subBlock, {'RowSpan'}, {'Range of rows'}};
               saved_params{k+5} = {subBlock, {'RowStartMode'}, {'Index'}};
               saved_params{k+6} = {subBlock, {'RowStartIndex'}, {N1}};
               saved_params{k+7} = {subBlock, {'RowEndMode'}, {'Index'}};
               saved_params{k+8} = {subBlock, {'RowEndIndex'}, {N2}};
               saved_params{k+9} = {subBlock, {'ColSpan'}, {'Range of columns'}};
               saved_params{k+10} = {subBlock,{'ColStartMode'}, {'First'}};
               saved_params{k+11} = {subBlock,{'ColEndMode'}, {'Index'}};
               saved_params{k+12} = {subBlock,{'ColEndIndex'}, {num_chans}};
               subBlock = [block, '/Unbuffer'];
               saved_params{k+13} = {subBlock, {'ic'}, {ic}};
               k = k + 14;
           case 'dspswit2/Commutator'
               block = blks{i}.Block;
               set_param(block, 'ReferenceBlock', 'dsp_r11_replacements/Commutator');
               sybsys_to_break_links{m} = block;
               m = m + 1;
           case 'dspstat2/Maximum'
               block = blks{i}.Block;
               [saved_params k] = ...
                   handle_reset_ports(block, 'dspstat3/Maximum', ...
                   k, saved_params);
           case 'dspstat2/Minimum'
               block = blks{i}.Block;
               [saved_params k] = ...
                   handle_reset_ports(block, 'dspstat3/Minimum', ...
                   k, saved_params);
           case 'dspstat2/Mean'
               block = blks{i}.Block;
               [saved_params k] = ...
                   handle_reset_ports_1(block, 'dspstat3/Mean', ...
                   k, saved_params);
           case ['dspstat2/Standard',char(10), 'Deviation']
               block = blks{i}.Block;
               [saved_params k] = ...
                   handle_reset_ports_1(block, ['dspstat3/Standard',char(10), 'Deviation'], ...
                   k, saved_params);
           case 'dspstat2/Variance'
               block = blks{i}.Block;
               [saved_params k] = ...
                   handle_reset_ports_1(block, 'dspstat3/Variance', ...
                   k, saved_params);
           case 'dspstat2/RMS'
               block = blks{i}.Block;
               [saved_params k] = ...
                   handle_reset_ports_1(block, 'dspstat3/RMS', ...
                   k, saved_params);            
           otherwise
               for j=1:1:size(ref_table(:))
                   if strcmp(rblock, ref_table{j}{1})               
                        block = blks{i}.Block;                        
                        set_param(block, 'ReferenceBlock', char(ref_table{j}{2}));                        
                        param_names =  get_param(block, 'MaskNames');
                        param_values = get_param(block, 'MaskValues');
                        % Fix parameter names that have changed since R11
                        [messages param_names param_values] = ...
                            update_params(rblock, block, param_names, param_values, messages); 
                        if size(param_names) > 0
                            saved_params{k} = {block, param_names, param_values};
                            k = k + 1;
                        end
                   end
               end
       end
   end
end

function message = replace_filter_design_blocks(system)
% Using set_param to change the reference block can produce a model in
% which the FDATool doesn't save properly. This techniques will be used
% instead for these types of blocks
    replaced_names = [];
    % This library must be loaded before calling replace_blocks
    load_system('dsparch4');
    replaced_names{1} = replace_block(system,'Analog Filter Design',['dsparch4/Analog',char(10),'Filter Design'],'noprompt');
    replaced_names{2} = replace_block(system,'Digital FIR Filter Design',['dsparch4/Digital',char(10),'Filter Design'],'noprompt');
    replaced_names{3} = replace_block(system,'Digital FIR Raised Cosine Filter Design',['dsparch4/Digital',char(10),'Filter Design'],'noprompt');
    replaced_names{4} = replace_block(system,'Least Squares FIR Filter Design',['dsparch4/Digital',char(10),'Filter Design'],'noprompt');
    replaced_names{5} = replace_block(system,'Digital IIR Filter Design',['dsparch4/Digital',char(10),'Filter Design'],'noprompt');
    replaced_names{6} = replace_block(system,'Yule-Walker IIR Filter Design',['dsparch4/Digital',char(10),'Filter Design'],'noprompt');
    replaced_names{7} = replace_block(system,'Remez FIR Filter Design',['dsparch4/Digital',char(10),'Filter Design'],'noprompt');
    
    count = 0;
    for i=1:1:7
        count = count + size(replaced_names{i},1);
    end
    
    message = [];
    if count > 0
        message = sprintf('\n');
        if count > 1
            message = sprintf('%s    The following R11 DSP Blockset filter design blocks were converted to\n', message);
             message = sprintf('%s    current Signal Processing Blockset filter design blocks.\n', message);
             message = sprintf('%s    You will need to redesign these filters.\n', message);
        end
        if count == 1
             message = sprintf('%s    The following R11 DSP Blockset filter design block was converted to\n', message);
             message = sprintf('%s    a current Signal Processing Blockset filter design block.\n', message);
             message = sprintf('%s    You will need to redesign this filter.\n', message);
        end
        for i=1:1:7
            if size(replaced_names{i},1) > 0
                for j=1:1:size(replaced_names{i},1)
                     message = sprintf('%s%s\n', message, replaced_names{i}{j});
                end
            end
        end
         message = sprintf('%s\n', message);
    end
end

function [saved_params k] = handle_reset_ports(block, newRef, k, ...
    saved_params)
% Set reset port parameter where parameter type has changed
    set_param(block, 'ReferenceBlock', newRef);
    fcn = get_param(block, 'fcn');
    if strcmp(fcn, 'Running')
        % Parameter changed from a checkbox to a popup.
        reset = get_param(block, 'reset');
        switch reset
           case 'on'                       
               saved_params{k} = {block, {'reset'}, {'Non-zero sample'}};              
           case 'off'
               saved_params{k} = {block, {'reset'}, {'None'}};
        end
        k = k + 1;
    end
end

function [saved_params k] = handle_reset_ports_1(block, newRef, k, ...
    saved_params)
% Another set reset port parameter where parameter type has changed
    set_param(block, 'ReferenceBlock', newRef);
    fcn = get_param(block, 'run');
    if strcmp(fcn, 'on')
        % Parameter changed from a checkbox to a popup.
        reset = get_param(block, 'reset');
        switch reset
           case 'on'                       
               saved_params{k} = {block, {'reset_popup'}, {'Non-zero sample'}};              
           case 'off'
               saved_params{k} = {block, {'reset_popup'}, {'None'}};
        end
        k = k + 1;
    end
end

function restore_parameters(saved_params)
% Write back parameters which have been reset to library defaults by
% model updated.
    for i=1:1:size(saved_params(:))
        for j=1:1:size(saved_params{i}{2})
            try
                set_param(saved_params{i}{1}, ...
                    saved_params{i}{2}{j}, ...
                    saved_params{i}{3}{j});
            catch
                % Filter out some errors that can't be helped
                errors = check_last_error();
                if size(errors,2)        
                    fprintf('    During model update:\n%s\n',errors);
                end
            end
        end
    end
end

function [messages param_names param_values] = update_params(rblock, mblock, param_names, param_values, messages)
% For those parameters whos names are different, update the names.
% Add some new parameters for some block types.
% Also, a good place to warn for post-convertion actions on specific blocks.
    switch rblock
        case 'dspsrcs2/Chirp'
            messages = sprintf('%s    You must convert degrees to radians\n    for a non-zero initial phase in block\n%s\n',messages, mblock);            
            param_names = update_param_name(param_names, 'phi', 'phase');
            param_names = update_param_name(param_names, 'method', 'sweep'); 
        case ['dspadpt2/LMS',char(10),'Adaptive Filter']
            param_names = update_param_name(param_names, 'n', 'L');
        case ['dspadpt2/RLS',char(10),'Adaptive Filter']
            param_names = update_param_name(param_names, 'Ntaps', 'L');
        case 'dspbdsp2/LPC'
            param_names = update_param_name(param_names, 'ord', 'order');
        case ['dspbdsp2/Triggered Signal',char(10),'From Workspace']
            param_names = update_param_name(param_names, 'X', 'Signal');
            param_names = update_param_name(param_names, 'trigtype', 'TriggerType');
        case ['dsparch2/Biquadratic',char(10),'Filter']
            param_names = update_param_name(param_names, 'sos', 'BiQuadCoeffs');
            param_names = update_param_name(param_names, 'ic', 'IC');
            param_names{size(param_names,1)+1} = 'TypePopup';
            param_values{size(param_values,1)+1} = 'IIR (poles & zeros)';
            param_names{size(param_names,1)+1} = 'IIRFiltStruct';
            param_values{size(param_values,1)+1} = 'Biquad direct form II transposed (SOS)';
        case ['dsparch2/Direct-Form II',char(10),'Transpose Filter']
            param_names = update_param_name(param_names, 'num', 'NumCoeffs');
            param_names = update_param_name(param_names, 'den', 'DenCoeffs');
            param_names = update_param_name(param_names, 'ic', 'IC');
            param_names{size(param_names,1)+1} = 'TypePopup';
            param_values{size(param_values,1)+1} = 'IIR (poles & zeros)';
            param_names{size(param_names,1)+1} = 'IIRFiltStruct';
            param_values{size(param_values,1)+1} = 'Direct form II transposed';
        case ['dsparch2/Time-Varying Direct-',char(10),'Form II Transpose Filter']            
            param_names = update_param_name(param_names, 'ic', 'IC');            
            NumDen = get_param(mblock, 'NumDen');
            param_names{size(param_names,1)+1} = 'TypePopup';
            switch NumDen
                case 'Pole-Zero (IIR)'
                    param_values{size(param_values,1)+1} = 'IIR (poles & zeros)';
                    param_names{size(param_names,1)+1} = 'IIRFiltStruct';
                    param_values{size(param_values,1)+1} = 'Direct form II transposed';
                case 'All-Zero (FIR)'
                    param_values{size(param_values,1)+1} = 'FIR (all zeros)';
                    param_names{size(param_names,1)+1} = 'FIRFiltStruct';
                    param_values{size(param_values,1)+1} = 'Direct form transposed';
                case 'All-Pole (AR)'
                    param_values{size(param_values,1)+1} = 'IIR (all poles)';
                    param_names{size(param_names,1)+1} = 'AllPoleFiltStruct';
                    param_values{size(param_values,1)+1} = 'Direct form transposed';
            end                                                
            param_names{size(param_names,1)+1} = 'CoeffSource';
            param_values{size(param_values,1)+1} = 'Input port(s)';
        case ['dsparch2/Time-Varying',char(10),'Lattice Filter']
            param_names = update_param_name(param_names, 'ic', 'IC');
            %param_names = update_param_name(param_names, 'FiltPerFrame', 'FiltPerSampPopup');
            param_names{size(param_names,1)+1} = 'TypePopup';
            ARMA = get_param(mblock, 'ARMA');
            if strcmp(ARMA, 'All-Zero (MA)')            
                param_values{size(param_values,1)+1} = 'FIR (all zeros)';
                param_names{size(param_names,1)+1} = 'FIRFiltStruct';
                param_values{size(param_values,1)+1} = 'Lattice MA';
            else
                param_values{size(param_values,1)+1} = 'IIR (all poles)';
                param_names{size(param_names,1)+1} = 'AllPoleFiltStruct';
                param_values{size(param_values,1)+1} = 'Lattice AR';
            end                        
            param_names{size(param_names,1)+1} = 'CoeffSource';
            param_values{size(param_values,1)+1} = 'Input port(s)';
        case ['dspelem2/Variable',char(10),'Selector']
            param_names = update_param_name(param_names, 'ic', 'IC');
        case ['dsplinalg/Backward',char(10),'Substitution']
            param_names = update_param_name(param_names, 'unit', 'Unit');
        case ['dsplinalg/Forward',char(10),'Substitution']
            param_names = update_param_name(param_names, 'unit', 'Unit');
        case 'dsplinalg/Levinson Solver'
            param_names = update_param_name(param_names, 'fcn', 'coeffOutFcn');
            param_names = update_param_name(param_names, 'otype', 'zeroInpHandling');
        case ['dspmlti2/Dyadic Analysis',char(10),'Filter Bank']
            param_names = update_param_name(param_names, 'hl', 'LPF');
            param_names = update_param_name(param_names, 'hh', 'HPF');
            param_names = update_param_name(param_names, 'numLevels', 'NumLevels');
        case ['dspmlti2/Dyadic Synthesis',char(10),'Filter Bank']
            param_names = update_param_name(param_names, 'hl', 'LPF');
            param_names = update_param_name(param_names, 'hh', 'HPF');
            param_names = update_param_name(param_names, 'numLevels', 'NumLevels');
        case ['dspmtrx2/Matrix',char(10),'From Workspace']
            param_names = update_param_name(param_names, 'U', 'X');
        case ['dspparest2/Covariance AR',char(10),'Estimator']
            param_names = update_param_name(param_names, 'ord', 'P');
        case ['dspparest2/Modified Covariance',char(10),'AR Estimator']
            param_names = update_param_name(param_names, 'ord', 'P');
        case ['dspsnks2/Signal',char(10),'To Workspace']
            param_names = update_param_name(param_names, 'Buffer', 'MaxDataPoints');
        case ['dspsnks2/Triggered Matrix',char(10),'To Workspace']
            param_names = update_param_name(param_names, 'matname', 'VariableName');
        case ['dspsnks2/Matrix',char(10),'Viewer']
            param_names = update_param_name(param_names, 'CMap', 'CMapStr');
        case ['dspsrcs2/Discrete ',char(10),'Impulse']
            param_names = update_param_name(param_names, 'Datatype', 'dataType');
        case ['dspsrcs2/Matrix',char(10),'Constant']
            param_names = update_param_name(param_names, 'M', 'Value');
        case ['dspsrcs2/Matrix',char(10),'From Workspace']
            param_names = update_param_name(param_names, 'U', 'X');
        case ['dspsrcs2/Random',char(10),'Source']
            param_names = update_param_name(param_names, 'Min', 'MinVal');
            param_names = update_param_name(param_names, 'Max', 'MaxVal');
            param_names = update_param_name(param_names, 'Mean', 'MeanVal');
            param_names = update_param_name(param_names, 'Variance', 'VarVal');
            param_names = update_param_name(param_names, 'Inherit', 'IsInherit');
        case 'dspbdsp2/Downsample'
            param_names = update_param_name(param_names, 'mode', 'fmode');
    end            
end

function param_names = update_param_name(param_names, oldname, newname)
% Update the name of a single parameter for a single block
    for i=1:1:size(param_names)
        if strcmp(param_names{i}, oldname)
            param_names{i} = newname;
            return;
        end
    end
end

function break_replacement_links(sybsys_to_break_links)
% Break lines to subsystem in temp library. Probably only used for
% subsystem that replaces Partial Unbuffer block.
    for i=1:1:size(sybsys_to_break_links(:))
        set_param(sybsys_to_break_links{i}, 'LinkStatus', 'None');
    end
end

function [disabled references] = search_for_r11(blks)
% Search for instances of R11 block and disabled library links
    r11_libs = get_r11_libs();
    disabled = 0;
    references = 0;
    for i=1:1:size(blks)
        c = strcmp(blks(i).LinkStatus, 'resolved');
        if (c == false)        
            disabled = disabled + 1;
        end
        for j=1:1:size(r11_libs(:))
            if (strfind(blks(i).ReferenceBlock, char(r11_libs{j})))
                references = references + 1;
            end
        end
    end
end

function pruned_r11_blocks = find_blocks_to_replace(blks, ref_table)
% List is what is returned by the call to libinfo
% Returns a pruned list only containing R11 blocks that also are
% not contained within other R11 blocks
    r11_blocks = [];
    pruned_r11_blocks = [];
    k = 1;
    % First, find all R11 blocks in the model
    for i=1:1:size(blks)
        rblock = blks(i).ReferenceBlock;           
        for j=1:1:size(ref_table(:))
           if strcmp(rblock, ref_table{j}{1})
               r11_blocks{k} = blks(i);
               k = k + 1;
           end
        end
    end
    
    % Next, For each R11 block: Parse into a list of substrings where
    % each substring is delimited by '/' char. Handles '//' which can
    % be part of substrings correctly.
    parsed_r11_blocks = [];
    for i=1:1:size(r11_blocks(:))
        parsed_r11_blocks{i} = parse_block_name(r11_blocks{i}.Block);
    end
               
    k = 1;
    % Next, find R11 blocks that are not contained in other R11 blocks
    for i=1:1:size(r11_blocks(:))              
        parsed_block = parsed_r11_blocks{i};
        top = 1;
        for j=1:1:size(r11_blocks(:))
            if i == j
                continue;
            end                        
            parsed_r11_block = parsed_r11_blocks{j};
            same = 1;
            for n=1:1:size(parsed_r11_block,2)
                if n > size(parsed_block,2)
                    same = 0;
                    break;
                end
                if strcmp(parsed_block(n), parsed_r11_block(n))
                else
                    same = 0;
                    break;
                end
            end
            if same
                % r11_blocks{j}.Block is substring of block starting at position 1.
                % Hence r11_blocks{j}.Block contains block and block cannot be
                % a top-level block
                top = 0;
            end            
        end
        %ATTN! If next line is uncommented then pruning blocks within
        % blocks will be disabled.
        %top = 1;
        if top == 1
            % Found R11 block not contained in another R11 block
            pruned_r11_blocks{k} = r11_blocks{i};
            k = k + 1;
        end
    end
end

function parts = parse_block_name(name)
% Parse and return an array of strings consisting of the parts of
% the name between '/' tokens that are not adjacent to another '/'.
    parts = [];
    i = 1;
    n = 1;
    begin = 1;
    while 1
        if i > size(name,2)
            % Will occur if name ends in '//'
            i = size(name,2);
        end
        if i == size(name,2)
           part = [];
           k = 1;
           for j = begin:1:size(name,2)
                part(k) = name(j); 
                k = k + 1;
           end
           parts{n} = char(part);
           break;
        end
        if i < size(name,2)            
            if name(i) == '/' && name(i+1) == '/'
                % Pairs of '//' are part of a block name
                i = i + 2;
                continue;
            end
        end
        if name(i) == '/'
            k = 1;
            part = [];
            for j = begin:1:i-1
                part(k) = name(j);
                k = k + 1;
            end
            parts{n} = char(part);
            n = n + 1;
            i = i + 1;
            begin = i;
            continue;
        end
        i = i + 1;
    end
end

function report = check_last_error
% Function to filter out errors that we don't want to report
    report = [];
    remain = lasterr;    
    while 1
        if size(remain,2) == 0
            if size(report,2)
                report = sprintf('%s\n',report); 
            end
            return;
        end
        [next remain] = strtok(remain, char(10));
        if strcmp(next, 'Error using ==> set_param')
        	continue;
        end        
        if strfind(next, 'for parameter ''reset''')
        	continue;
        end
        if strfind(next, 'for parameter ''userDeviceID''')
        	continue;
        end
        if strfind(next, 'Invalid setting in To Wave Device block (mask)')
            continue;
        end
        if strfind(next, 'Invalid setting in From Wave Device block (mask)')
            continue;
        end
        if strfind(next, 'Initialization commands cannot be evaluated.')
            continue;
        end
        if strfind(next, 'does not have a parameter named')
            continue;
        end
        % The next two seem to be bogus so filtering out
        if strfind(next, 'Error reported by S-function ''sdspsubmtrx''')
            continue;
        end
        if strfind(next, 'Ending row index cannot be less than the starting row index')
            continue;
        end
        if size(report,2)
            report = sprintf('%s\n%s',report, next);
        else
            report = next;
        end
    end    
end

function r11_libs = get_r11_libs()
% Get a list of all the R11 libraries
    r11_libs = {...
        {'dspbuff2/'},{'dspadpt2/'},{'dsparch2/'},{'dspbdsp2/'},...
        {'dspddes2/'},{'dsplinalg/'},{'dspmlti2/'},{'dspmtrx2/'},...
        {'dspparest2/'},{'dspquant/'},{'dspsnks2/'},{'dspspect2/'},...
        {'dspstat2/'},{'dspswit2/'},{'dspsrcs2/'},{'dspelem2/'},...
        {'dspvect2/'},{'dspxfrm2/'}
        };
end

function ref_table = Get_Reference_table()
% Return table of mappings of R11 blocks to current blocks
% Note: Some mappings are to the empty string. These are handled
% programatically in function replace_R11_blocks.
    ref_table = { ...
        {{['dspbuff2/Partial', char(10), 'Unbuffer']},{''}}, ...
        {{'dspswit2/Commutator'},{''}}, ...        
        {{'dspstat2/Maximum'},{''}}, ...
        {{'dspstat2/Minimum'},{''}}, ...
        {{'dspstat2/Mean'},{''}}, ...
        {{['dspstat2/Standard',char(10), 'Deviation']},{''}}, ...
        {{'dspstat2/Variance'},{''}}, ...
        {{'dspstat2/RMS'},{''}}, ...        
        {{['dspadpt2/LMS',char(10),'Adaptive Filter']},{'dspadpt3/LMS Filter'}}, ...
        {{['dspadpt2/RLS',char(10),'Adaptive Filter']},{'dspadpt3/RLS Filter'}}, ...
        {{['dspadpt2/Kalman',char(10),'Adaptive Filter']},{['dspadpt3/Kalman',char(10),'Adaptive Filter']}}, ...        
        {{['dsparch2/Overlap-Save',char(10),'FFT Filter']},{['dsparch4/Overlap-Save',char(10),'FFT Filter']}}, ...
        {{['dsparch2/Overlap-Add',char(10),'FFT Filter']},{['dsparch4/Overlap-Add',char(10),'FFT Filter']}}, ...        
        {{'dspbdsp2/Analytic Signal'},{'dspxfrm3/Analytic Signal'}}, ...
        {{'dspbdsp2/Detrend'},{'dspstat3/Detrend'}}, ...
        {{'dspbdsp2/LPC'},{['dsplp/Autocorrelation',char(10),'LPC']}}, ...
        {{'dspbuff2/Buffer'},{'dspbuff3/Buffer'}}, ...
        {{['dspbuff2/Triggered',char(10),'Shift Register']},{['dspbuff3/Triggered',char(10),'Delay Line']}}, ...
        {{'dsplinalg/Cholesky Solver'},{'dspsolvers/Cholesky Solver'}}, ...        
        {{'dsplinalg/LDL Solver'},{'dspsolvers/LDL Solver'}}, ...        
        {{'dsplinalg/LU Solver'},{'dspsolvers/LU Solver'}}, ...        
        {{['dsplinalg/Reciprocal',char(10),'Condition']},{['dspmtrx3/Reciprocal',char(10),'Condition']}}, ...
        {{'dspbuff2/Unbuffer'},{'dspbuff3/Unbuffer'}}, ...
        {{['dspddes2/Digital FIR',char(10),'Filter Design']},{['dsparch4/Digital',char(10),'Filter Design']}}, ...
        {{['dspddes2/Digital FIR Raised',char(10),'Cosine Filter Design']},{['dsparch4/Digital',char(10),'Filter Design']}}, ...
        {{['dspddes2/Least Squares FIR',char(10),'Filter Design']},{['dsparch4/Digital',char(10),'Filter Design']}}, ...    
        {{['dspddes2/Digital IIR',char(10),'Filter Design']},{['dsparch4/Digital',char(10),'Filter Design']}}, ... 
        {{['dspddes2/Yule-Walker IIR',char(10),'Filter Design']},{['dsparch4/Digital',char(10),'Filter Design']}}, ... 
        {{['dspddes2/Remez FIR',char(10),'Filter Design']},{['dsparch4/Digital',char(10),'Filter Design']}}, ... 
        {{['dspelem2/Variable',char(10),'Selector']}, {['dspindex/Variable',char(10),'Selector']}}, ...
        {{['dspparest2/Covariance AR',char(10),'Estimator']},{['dspparest3/Covariance AR',char(10),'Estimator']}}, ...
        {{['dspparest2/Modified Covariance',char(10),'AR Estimator']},{['dspparest3/Modified Covariance',char(10),'AR Estimator']}}, ...
        {{['dspparest2/Yule-Walker AR',char(10),'Estimator']},{['dspparest3/Yule-Walker AR',char(10),'Estimator']}}, ...        
        {{['dspsnks2/Triggered Matrix',char(10),'To Workspace']},{['dspsnks4/Triggered',char(10),'To Workspace']}}, ...
        {{['dspsnks2/Triggered Signal',char(10),'To Workspace']},{['dspsnks4/Triggered',char(10),'To Workspace']}}, ...
        {{['dspsnks2/FFT',char(10),'Frame Scope']},{['dspsnks4/Spectrum',char(10),'Scope']}}, ...
        {{['dspsnks2/Buffered FFT',char(10),'Frame Scope']},{['dspsnks4/Spectrum',char(10),'Scope']}}, ...
        {{'dspspect2/Short-Time FFT'},{'dspspect3/Periodogram'}}, ...
        {{['dspspect2/Yule-Walker',char(10),'Method']},{['dspspect3/Yule-Walker',char(10),'Method']}}, ...
        {{'dspspect2/Covariance Method'},{'dspspect3/Covariance Method'}}, ...
        {{['dspspect2/Magnitude',char(10),'FFT']},{['dspspect3/Magnitude',char(10),'FFT']}}, ...
        {{'dspspect2/Burg Method'},{'dspspect3/Burg Method'}}, ...
        {{['dspspect2/Modified Covariance',char(10),'Method']},{['dspspect3/Modified Covariance',char(10),'Method']}}, ...        
        {{'dspsrcs2/Chirp'},{'dspsrcs4/Chirp'}}, ...
        {{['dspswit2/Edge',char(10),'Detector']},{['dspswit3/Edge',char(10),'Detector']}}, ...
        {{['dspswit2/Event-Count',char(10),'Comparator']},{['dspswit3/Event-Count',char(10),'Comparator']}}, ...
        {{['dspswit2/N-Sample',char(10),'Switch']},{['dspswit3/N-Sample',char(10),'Switch']}}, ...        
        {{'dspswit2/Distributor'},{'dspbuff3/Buffer'}}, ...    
        {{'dspvect2/Correlation'},{'dspstat3/Correlation'}}, ...
        {{['dspxfrm2/Complex',char(10),'Cepstrum']},{['dspxfrm3/Complex',char(10),'Cepstrum']}}, ...
        {{['dspxfrm2/Real',char(10),'Cepstrum']},{['dspxfrm3/Real',char(10),'Cepstrum']}}, ...        
        {{['dsparch2/Biquadratic',char(10),'Filter']},{'dsparch4/Digital Filter'}}, ...
        {{['dsparch2/Direct-Form II',char(10),'Transpose Filter']},{'dsparch4/Digital Filter'}}, ...
        {{['dsparch2/Time-Varying Direct-',char(10),'Form II Transpose Filter']},{'dsparch4/Digital Filter'}}, ...
        {{['dsparch2/Time-Varying',char(10),'Lattice Filter']},{'dsparch4/Digital Filter'}}, ...
        {{['dsparch2/Filter',char(10),'Realization',char(10),'Wizard']},{['dsparch4/Filter',char(10),'Realization',char(10),'Wizard']}}, ...                
        {{'dspbdsp2/Downsample'},{'dspsigops/Downsample'}}, ...
        {{'dspbdsp2/Integer Delay'},{'dspsigops/Delay'}}, ...        
        {{'dspbdsp2/Repeat'},{'dspsigops/Repeat'}}, ...
        {{['dspbdsp2/Triggered Signal',char(10),'From Workspace']},{['dspsigops/Triggered Signal',char(10),'From Workspace']}}, ...
        {{'dspbdsp2/Upsample'},{'dspsigops/Upsample'}}, ...
        {{['dspbdsp2/Variable',char(10),'Fractional Delay']},{['dspsigops/Variable',char(10),'Fractional Delay']}}, ...
        {{['dspbdsp2/Variable',char(10),'Integer Delay']},{['dspsigops/Variable',char(10),'Integer Delay']}}, ...
        {{['dspbdsp2/Window',char(10),'Function']},{['dspsigops/Window',char(10),'Function']}}, ...
        {{'dspbdsp2/Zero Pad'},{'dspsigops/Zero Pad'}}, ...        
        {{'dspbuff2/Rebuffer'},{'dspbuff3/Buffer'}}, ...
        {{'dspbuff2/Shift Register'},{'dspbuff3/Delay Line'}}, ...                
        {{'dspbuff2/Stack'},{'dspbuff3/Stack'}}, ...
        {{'dspbuff2/Queue'},{'dspbuff3/Queue'}}, ...        
        {{['dspddes2/Analog',char(10),'Filter Design']},{['dsparch4/Analog',char(10),'Filter Design']}}, ...        
        {{['dspelem2/Complex',char(10),'Exponential']}, {['dspmathops/Complex',char(10),'Exponential']}}, ...
        {{['dspelem2/Contiguous',char(10),'Copy']}, {['dspobslib/Contiguous',char(10),'Copy']}}, ...        
        {{['dspelem2/Polynomial',char(10),'Evaluation']}, {['dsppolyfun/Polynomial',char(10),'Evaluation']}}, ...
        {{'dspelem2/dB'}, {'dspmathops/dB Conversion'}}, ...
        {{'dspelem2/dB Gain'}, {'dspmathops/dB Gain'}}, ...
        {{['dspelem2/Inherit',char(10),'Complexity']}, {['dspsigattribs/Inherit',char(10),'Complexity']}}, ...        
        {{['dsplinalg/Cholesky',char(10),'Factorization']},{['dspfactors/Cholesky',char(10),'Factorization']}}, ...        
        {{'dsplinalg/LDL Factorization'},{'dspfactors/LDL Factorization'}}, ...        
        {{'dsplinalg/LU Factorization'},{'dspfactors/LU Factorization'}}, ...        
        {{'dsplinalg/QR Factorization'},{'dspfactors/QR Factorization'}}, ...
        {{'dsplinalg/QR Solver'},{'dspsolvers/QR Solver'}}, ...
        {{['dsplinalg/Backward',char(10),'Substitution']},{['dspsolvers/Backward',char(10),'Substitution']}}, ...
        {{['dsplinalg/Forward',char(10),'Substitution']},{['dspsolvers/Forward',char(10),'Substitution']}}, ...
        {{'dsplinalg/Levinson Solver'},{'dspsolvers/Levinson-Durbin'}}, ...         
        {{['dspmlti2/FIR',char(10),'Decimation']},{['dspmlti4/FIR',char(10),'Decimation']}}, ...
        {{['dspmlti2/FIR',char(10),'Interpolation']},{['dspmlti4/FIR',char(10),'Interpolation']}}, ...
        {{['dspmlti2/FIR Rate',char(10),'Conversion']},{['dspmlti4/FIR Rate',char(10),'Conversion']}}, ...
        {{['dspmlti2/Dyadic Analysis',char(10),'Filter Bank']},{['dspmlti4/Dyadic Analysis',char(10),'Filter Bank']}}, ...
        {{['dspmlti2/Dyadic Synthesis',char(10),'Filter Bank']},{['dspmlti4/Dyadic Synthesis',char(10),'Filter Bank']}}, ...
        {{['dspmlti2/Wavelet',char(10),'Analysis']},{['dspobslib/Wavelet',char(10),'Analysis']}}, ...
        {{['dspmlti2/Wavelet',char(10),'Synthesis']},{['dspobslib/Wavelet',char(10),'Synthesis']}}, ...        
        {{['dspmtrx2/Matrix',char(10),'Multiplication']},{['simulink/Math',char(10),'Operations/Product']}}, ...
        {{['dspmtrx2/Matrix',char(10),'Square']},{['dspmtrx3/Matrix',char(10),'Square']}}, ...
        {{'dspmtrx2/Transpose'},{'dspmtrx3/Transpose'}}, ...
        {{'dspmtrx2/Toeplitz'},{'dspmtrx3/Toeplitz'}}, ...
        {{'dspmtrx2/Submatrix'},{'dspmtrx3/Submatrix'}}, ...
        {{['dspmtrx2/Matrix',char(10),'Constant']},{'simulink/Sources/Constant'}}, ...
        {{['dspmtrx2/Matrix',char(10),'From Workspace']},{['dspsrcs4/Signal From',char(10),'Workspace']}}, ...
        {{['dspmtrx2/Matrix',char(10),'Scaling']},{['dspmtrx3/Matrix',char(10),'Scaling']}}, ...
        {{['dspmtrx2/Matrix',char(10),'Sum']},{['dspmtrx3/Matrix',char(10),'Sum']}}, ...
        {{['dspmtrx2/Matrix',char(10),'Product']},{['dspmtrx3/Matrix',char(10),'Product']}}, ...
        {{['dspmtrx2/Matrix ',char(10),'1-Norm']},{['dspmtrx3/Matrix ',char(10),'1-Norm']}}, ...
        {{['dspmtrx2/Constant Diagonal',char(10),'Matrix']},{['dspmtrx3/Constant Diagonal',char(10),'Matrix']}}, ...
        {{['dspmtrx2/Matrix',char(10),'To Workspace']},{'simulink/Sinks/To Workspace'}}, ...
        {{['dspmtrx2/Extract Triangular',char(10),'Matrix']},{['dspmtrx3/Extract Triangular',char(10),'Matrix']}}, ...
        {{'dspmtrx2/Extract Diagonal'},{'dspmtrx3/Extract Diagonal'}}, ...
        {{['dspmtrx2/Create Diagonal',char(10),'Matrix']},{['dspmtrx3/Create Diagonal',char(10),'Matrix']}}, ...
        {{['dspmtrx2/Permute',char(10),'Matrix']},{['dspmtrx3/Permute',char(10),'Matrix']}}, ...
        {{'dspmtrx2/Reshape'},{['simulink/Math',char(10),'Operations/Reshape']}}, ...        
        {{['dspparest2/Burg AR',char(10),'Estimator']},{['dspparest3/Burg AR',char(10),'Estimator']}}, ...        
        {{['dspquant/Uniform',char(10),'Encoder']},{['dspquant2/Uniform',char(10),'Encoder']}}, ...
        {{['dspquant/Uniform',char(10),'Decoder']},{['dspquant2/Uniform',char(10),'Decoder']}}, ...        
        {{['dspsnks2/Matrix',char(10),'To Workspace']},{'simulink/Sinks/To Workspace'}}, ...
        {{['dspsnks2/Signal',char(10),'To Workspace']},{['dspsnks4/Signal To',char(10),'Workspace']}}, ...        
        {{['dspsnks2/Matrix',char(10),'Viewer']},{['dspsnks4/Matrix',char(10),'Viewer']}}, ...
        {{['dspsnks2/To Wave',char(10),'Device']},{['dspwin32/To Wave',char(10),'Device']}}, ...
        {{['dspsnks2/To Wave',char(10),'File']},{['dspwin32/To Wave',char(10),'File']}}, ...
        {{['dspsnks2/Time',char(10),'Frame Scope']},{['dspsnks4/Vector',char(10),'Scope']}}, ...
        {{['dspsnks2/Frequency',char(10),'Frame Scope']},{['dspsnks4/Vector',char(10),'Scope']}}, ...
        {{['dspsnks2/User-defined',char(10),'Frame Scope']},{['dspsnks4/Vector',char(10),'Scope']}}, ...                
        {{'dspstat2/Histogram'},{'dspstat3/Histogram'}}, ...
        {{'dspstat2/Sort'},{'dspstat3/Sort'}}, ...
        {{'dspstat2/Median'},{'dspstat3/Median'}}, ...                        
        {{['dspsrcs2/Constant Diagonal',char(10),'Matrix']},{['dspsrcs4/Constant Diagonal',char(10),'Matrix']}}, ...
        {{['dspsrcs2/Discrete',char(10),'Constant']},{['dspsrcs4/DSP',char(10),'Constant']}}, ...
        {{['dspsrcs2/Discrete ',char(10),'Impulse']},{['dspsrcs4/Discrete ',char(10),'Impulse']}}, ...
        {{['dspsrcs2/From Wave',char(10),'Device']},{['dspwin32/From Wave',char(10),'Device']}}, ...
        {{['dspsrcs2/From Wave',char(10),'File']},{['dspwin32/From Wave',char(10),'File']}}, ...
        {{['dspsrcs2/Matrix',char(10),'Constant']},{['dspsrcs4/DSP',char(10),'Constant']}}, ...
        {{['dspsrcs2/Matrix',char(10),'From Workspace']},{['dspsrcs4/Signal From',char(10),'Workspace']}}, ...
        {{'dspsrcs2/Multiphase Clock'},{'dspsrcs4/Multiphase Clock'}}, ...
        {{['dspsrcs2/N-Sample',char(10),'Enable']},{['dspswit3/N-Sample',char(10),'Enable']}}, ...
        {{['dspsrcs2/Random',char(10),'Source']},{['dspsrcs4/Random',char(10),'Source']}}, ...
        {{'dspsrcs2/Sine Wave'},{'dspsrcs4/Sine Wave'}}, ...
        {{['dspsrcs2/Signal From',char(10),'Workspace']},{['dspsrcs4/Signal From',char(10),'Workspace']}}, ...        
        {{'dspswit2/Counter'},{'dspswit3/Counter'}}, ...        
        {{'dspswit2/Multiphase Clock'},{'dspswit3/Multiphase Clock'}}, ...
        {{['dspswit2/Sample',char(10),'and Hold']},{['dspsigops/Sample',char(10),'and Hold']}}, ...
        {{['dspswit2/N-Sample',char(10),'Enable']},{['dspswit3/N-Sample',char(10),'Enable']}}, ...            
        {{'dspvect2/Autocorrelation'},{'dspstat3/Autocorrelation'}}, ...
        {{'dspvect2/Convolution'},{'dspsigops/Convolution'}}, ...        
        {{['dspvect2/Cumulative',char(10),'Sum']},{['dspmathops/Cumulative',char(10),'Sum']}}, ...
        {{'dspvect2/Difference'},{'dspmathops/Difference'}}, ...
        {{'dspvect2/Normalization'},{'dspmathops/Normalization'}}, ...
        {{'dspvect2/Unwrap'},{'dspsigops/Unwrap'}}, ...        
        {{'dspxfrm2/FFT'},{'dspxfrm3/FFT'}}, ...
        {{'dspxfrm2/DCT'},{'dspxfrm3/DCT'}}, ...
        {{'dspxfrm2/IFFT'},{'dspxfrm3/IFFT'}}, ...
        {{'dspxfrm2/IDCT'},{'dspxfrm3/IDCT'}}, ...        
        };
end

Contact us