function names = findTopLevelHDLNames(~, modelName)
% NAMES = FINDTOPLEVELHDLNAMES(THIS) Return a cell array of possible HDL
% code gen subsystems/model references

%   Copyright 2005-2014 The MathWorks, Inc.

narginchk(2, 2);
names = {};

if isempty(modelName) || ~any(strcmp(find_system('flat'), modelName))
    return;
end
% @todo update the usage of edit-time filter filterOutInactiveVariantSubsystemChoices(),
% instead use the post-compile filter activeVariants() - g2603139
blks = find_system(modelName, 'LookUnderMasks','all',...
    'MatchFilter', @Simulink.match.internal.filterOutInactiveVariantSubsystemChoices, ... % look only inside active choice of VSS
    'BlockType','SubSystem');
try
    refs = get_param(blks,'ReferenceBlock');
catch me
    % There is an invalid block specified in blks.  This can happen when the DUT
    % subsystem is being transformed into a Variant subsystem.
    if strcmp(me.identifier, 'Simulink:Commands:GetParamInvalidFirstArgument')
        newblks = {};
        refs = {};
        for ii = 1:numel(blks)
            try
                ref = get_param(blks{ii}, 'ReferenceBlock');
                newblks{end+1} = blks{ii}; %#ok<AGROW>
                refs{end+1} = ref; %#ok<AGROW>
            catch
                % If the get_param fails, ignore that blk and continue on.
            end
        end
    else
        me.rethrow;
    end
    blks = newblks;
end

% @todo update the usage of edit-time filter filterOutInactiveVariantSubsystemChoices(),
% instead use the post-compile filter activeVariants() - g2603139
mdlrefs = find_system(modelName, 'LookUnderMasks','all',...
    'MatchFilter', @Simulink.match.internal.filterOutInactiveVariantSubsystemChoices, ... % look only inside active choice of VSS
    'BlockType','ModelReference');
names = cell(numel(mdlrefs) + 1, 1);
% First and default is whole model
names{1} = modelName;
for ii = 1:numel(mdlrefs)
    names{ii+1} = mdlrefs{ii};
end

for ii = 1:length(refs)
    % Try to remove SubSystems that don't make sense as an HDL top-level
    % 1.  Stateflow is special and should be supported since it is a
    %     subsystem.
    % 2.  If the block has a reference block (it is from a library) then
    %     check to see if it is from a simulink library or another
    %     blockset library we know about
    % 3.  Remove any systems that do not contain any blocks; this catches
    %     the demo "button" type subsystems.
    if ~strcmpi(get_param(blks{ii}, 'SFBlockType'), 'NONE')
        % G372730 do nothing for SF blocks
    elseif ~isempty(refs{ii})
        sllasterror_val = sllasterror;
        [lastwarn_msg, lastwarn_msgid] = lastwarn;
        sllastwarn_val = sllastwarning;
        try
            lib = get_param(refs{ii},'Parent');
        catch me % G312546 - library may not be open, in which case,
              % ignore and go to the next block
              sllasterror(sllasterror_val);
              lastwarn(lastwarn_msg,lastwarn_msgid);
              sllastwarning(sllastwarn_val);
              continue;
        end
        if ~strncmp(lib, 'simulink/', 9)
            names{end+1} = blks{ii}; %#ok<AGROW>
        end
    elseif ~isempty(get_param(blks{ii},'Blocks'))
        names{end+1} = blks{ii}; %#ok<AGROW>
    end
end

% Replace \n, \r, \t, \f  in block names with space
names = sort(hdlfixblockname(names));
end
